xref: /haiku/src/add-ons/accelerants/radeon_hd/encoder.cpp (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
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 	uint32 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 	// Careful! The mapping of ucHPD_ID differs between atombios calls
641 	uint16 hpdID = connector_pick_atom_hpdid(connectorIndex);
642 
643 	switch (tableMinor) {
644 		case 1:
645 			args.v1.ucAction = command;
646 			args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
647 
648 			if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
649 				args.v3.ucPanelMode = panelMode;
650 			else {
651 				args.v1.ucEncoderMode
652 					= display_get_encoder_mode(connectorIndex);
653 			}
654 
655 			if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
656 				|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
657 				args.v1.ucLaneNum = dpInfo->laneCount;
658 			} else if (dualLink)
659 				args.v1.ucLaneNum = 8;
660 			else
661 				args.v1.ucLaneNum = 4;
662 
663 			if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
664 				|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
665 				&& dpClock == 270000) {
666 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
667 			}
668 
669 			switch (connector->encoder.objectID) {
670 				case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
671 					args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
672 					break;
673 				case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
674 				case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
675 					args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
676 					break;
677 				case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
678 					args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
679 					break;
680 			}
681 
682 			if (linkB)
683 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
684 			else
685 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
686 			break;
687 		case 2:
688 		case 3:
689 			args.v3.ucAction = command;
690 			args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
691 
692 			if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
693 				args.v3.ucPanelMode = panelMode;
694 			else {
695 				args.v3.ucEncoderMode
696 					= display_get_encoder_mode(connectorIndex);
697 			}
698 
699 			if (args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP
700 				|| args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
701 				args.v3.ucLaneNum = dpInfo->laneCount;
702 			} else if (dualLink)
703 				args.v3.ucLaneNum = 8;
704 			else
705 				args.v3.ucLaneNum = 4;
706 
707 			if ((args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP
708 				|| args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
709 				&& dpClock == 270000) {
710 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
711 			}
712 
713 			args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex);
714 
715 			// TODO: get BPC
716 			switch (8) {
717 				case 0:
718 					args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
719 					break;
720 				case 6:
721 					args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
722 					break;
723 				case 8:
724 				default:
725 					args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
726 					break;
727 				case 10:
728 					args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
729 					break;
730 				case 12:
731 					args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
732 					break;
733 				case 16:
734 					args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
735 					break;
736 			}
737 			break;
738 		case 4:
739 			args.v4.ucAction = command;
740 			args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
741 
742 			if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
743 				args.v4.ucPanelMode = panelMode;
744 			else {
745 				args.v4.ucEncoderMode
746 					= display_get_encoder_mode(connectorIndex);
747 			}
748 
749 			if (args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP
750 				|| args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
751 				// Is DP?
752 				args.v4.ucLaneNum = dpInfo->laneCount;
753 				if (dpClock == 270000) {
754 					args.v4.ucConfig
755 						|= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
756 				} else if (dpClock == 540000) {
757 					args.v4.ucConfig
758 						|= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
759 				}
760 			} else if (dualLink) {
761 				// DualLink, double the lane numbers
762 				args.v4.ucLaneNum = 8;
763 			} else {
764 				args.v4.ucLaneNum = 4;
765 			}
766 			args.v4.acConfig.ucDigSel = digEncoderID;
767 
768 			// TODO: get BPC
769 			switch (8) {
770 				case 0:
771 					args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
772 					break;
773 				case 6:
774 					args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
775 					break;
776 				case 8:
777 				default:
778 					args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
779 					break;
780 				case 10:
781 					args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
782 					break;
783 				case 12:
784 					args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
785 					break;
786 				case 16:
787 					args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
788 					break;
789 			}
790 
791 			if (hpdID == 0xff)
792 				args.v4.ucHPD_ID = 0;
793 			else
794 				args.v4.ucHPD_ID = hpdID + 1;
795 			break;
796 		default:
797 			ERROR("%s: unknown tableMinor!\n", __func__);
798 	}
799 
800 	status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);
801 
802 	#if 0
803 	if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP
804 		&& panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) {
805 		dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1);
806 	}
807 	#endif
808 
809 	return result;
810 }
811 
812 
813 status_t
814 encoder_external_setup(uint32 connectorIndex, int command)
815 {
816 	TRACE("%s\n", __func__);
817 
818 	encoder_info* encoder
819 		= &gConnector[connectorIndex]->encoder;
820 	encoder_info* extEncoder
821 		= &gConnector[connectorIndex]->encoderExternal;
822 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
823 
824 	dp_info* dpInfo
825 		= &gConnector[connectorIndex]->dpInfo;
826 
827 	if (extEncoder->valid != true) {
828 		ERROR("%s: connector %" B_PRIu32 " doesn't have a valid "
829 			"external encoder!", __func__, connectorIndex);
830 		return B_ERROR;
831 	}
832 
833 	uint8 tableMajor;
834 	uint8 tableMinor;
835 
836 	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
837 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
838 		!= B_OK) {
839 		ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__);
840 		return B_ERROR;
841 	}
842 
843 	// Prepare AtomBIOS command arguments
844 	union externalEncoderControl {
845 		EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
846 		EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
847 	};
848 	union externalEncoderControl args;
849 	memset(&args, 0, sizeof(args));
850 
851 	int connectorObjectID
852 		= (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
853 			>> OBJECT_ID_SHIFT;
854 
855 	uint32 pixelClock = encoder->pll.pixelClock;
856 
857 	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
858 		tableMajor, tableMinor);
859 	switch (tableMajor) {
860 		case 1:
861 			// no options needed on table 1.x
862 			break;
863 		case 2:
864 			switch (tableMinor) {
865 				case 1:
866 				case 2:
867 					args.v1.sDigEncoder.ucAction = command;
868 					args.v1.sDigEncoder.usPixelClock
869 						= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
870 					args.v1.sDigEncoder.ucEncoderMode
871 						= display_get_encoder_mode(connectorIndex);
872 
873 					if (connector_is_dp(connectorIndex)) {
874 						if (dpInfo->linkRate == 270000) {
875 							args.v1.sDigEncoder.ucConfig
876 								|= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
877 						}
878 						args.v1.sDigEncoder.ucLaneNum
879 							= dpInfo->laneCount;
880 					} else if (pixelClock > 165000) {
881 						args.v1.sDigEncoder.ucLaneNum = 8;
882 					} else {
883 						args.v1.sDigEncoder.ucLaneNum = 4;
884 					}
885 					break;
886 				case 3:
887 				{
888 					args.v3.sExtEncoder.ucAction = command;
889 					if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) {
890 						args.v3.sExtEncoder.usConnectorId
891 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
892 					} else {
893 						args.v3.sExtEncoder.usPixelClock
894 							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
895 					}
896 
897 					args.v3.sExtEncoder.ucEncoderMode
898 						= display_get_encoder_mode(connectorIndex);
899 
900 					if (connector_is_dp(connectorIndex)) {
901 						if (dpInfo->linkRate == 270000) {
902 							args.v3.sExtEncoder.ucConfig
903 								|=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
904 						} else if (dpInfo->linkRate == 540000) {
905 							args.v3.sExtEncoder.ucConfig
906 								|=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
907 						}
908 						args.v1.sDigEncoder.ucLaneNum
909 							= dpInfo->laneCount;
910 					} else if (pixelClock > 165000) {
911 						args.v3.sExtEncoder.ucLaneNum = 8;
912 					} else {
913 						args.v3.sExtEncoder.ucLaneNum = 4;
914 					}
915 
916 					switch ((connectorFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) {
917 						case GRAPH_OBJECT_ENUM_ID1:
918 							TRACE("%s: external encoder 1\n", __func__);
919 							args.v3.sExtEncoder.ucConfig
920 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
921 							break;
922 						case GRAPH_OBJECT_ENUM_ID2:
923 							TRACE("%s: external encoder 2\n", __func__);
924 							args.v3.sExtEncoder.ucConfig
925 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
926 							break;
927 						case GRAPH_OBJECT_ENUM_ID3:
928 							TRACE("%s: external encoder 3\n", __func__);
929 							args.v3.sExtEncoder.ucConfig
930 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
931 							break;
932 					}
933 
934 					// TODO: don't set statically
935 					uint32 bitsPerColor = 8;
936 					switch (bitsPerColor) {
937 						case 0:
938 							args.v3.sExtEncoder.ucBitPerColor
939 								= PANEL_BPC_UNDEFINE;
940 							break;
941 						case 6:
942 							args.v3.sExtEncoder.ucBitPerColor
943 								= PANEL_6BIT_PER_COLOR;
944 							break;
945 						case 8:
946 						default:
947 							args.v3.sExtEncoder.ucBitPerColor
948 								= PANEL_8BIT_PER_COLOR;
949 							break;
950 						case 10:
951 							args.v3.sExtEncoder.ucBitPerColor
952 								= PANEL_10BIT_PER_COLOR;
953 							break;
954 						case 12:
955 							args.v3.sExtEncoder.ucBitPerColor
956 								= PANEL_12BIT_PER_COLOR;
957 							break;
958 						case 16:
959 							args.v3.sExtEncoder.ucBitPerColor
960 								= PANEL_16BIT_PER_COLOR;
961 							break;
962 					}
963 					break;
964 				}
965 				default:
966 					ERROR("%s: Unknown table minor version: "
967 						"%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
968 						tableMajor, tableMinor);
969 					return B_ERROR;
970 			}
971 			break;
972 		default:
973 			ERROR("%s: Unknown table major version: "
974 				"%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
975 				tableMajor, tableMinor);
976 			return B_ERROR;
977 	}
978 
979 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
980 }
981 
982 
983 status_t
984 encoder_analog_setup(uint32 connectorIndex, uint32 pixelClock, int command)
985 {
986 	TRACE("%s\n", __func__);
987 
988 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
989 
990 	int index = 0;
991 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
992 	memset(&args, 0, sizeof(args));
993 
994 	switch (gConnector[connectorIndex]->encoder.objectID) {
995 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
996 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
997 			index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
998 			break;
999 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1000 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1001 			index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
1002 			break;
1003 	}
1004 
1005 	args.ucAction = command;
1006 
1007 	if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
1008 		args.ucDacStandard = ATOM_DAC1_PS2;
1009 	else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1010 		args.ucDacStandard = ATOM_DAC1_CV;
1011 	else {
1012 		TRACE("%s: TODO, hardcoded NTSC TV support\n", __func__);
1013 		if (1) {
1014 			// NTSC, NTSC_J, PAL 60
1015 			args.ucDacStandard = ATOM_DAC1_NTSC;
1016 		} else {
1017 			// PAL, SCART. SECAM, PAL_CN
1018 			args.ucDacStandard = ATOM_DAC1_PAL;
1019 		}
1020 	}
1021 
1022 	args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1023 
1024 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
1025 }
1026 
1027 
1028 bool
1029 encoder_analog_load_detect(uint32 connectorIndex)
1030 {
1031 	TRACE("%s\n", __func__);
1032 
1033 	if (gConnector[connectorIndex]->encoderExternal.valid == true)
1034 		return encoder_dig_load_detect(connectorIndex);
1035 
1036 	return encoder_dac_load_detect(connectorIndex);
1037 }
1038 
1039 
1040 bool
1041 encoder_dac_load_detect(uint32 connectorIndex)
1042 {
1043 	TRACE("%s\n", __func__);
1044 
1045 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1046 	uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
1047 
1048 	if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0
1049 		&& (connectorFlags & ATOM_DEVICE_CV_SUPPORT) == 0
1050 		&& (connectorFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) {
1051 		ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n",
1052 			__func__, connectorIndex);
1053 		return false;
1054 	}
1055 
1056 	// *** tell the card we want to do a DAC detection
1057 
1058 	DAC_LOAD_DETECTION_PS_ALLOCATION args;
1059 	int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1060 	uint8 tableMajor;
1061 	uint8 tableMinor;
1062 
1063 	memset(&args, 0, sizeof(args));
1064 
1065 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
1066 		!= B_OK) {
1067 		ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n",
1068 			__func__);
1069 		return false;
1070 	}
1071 
1072 	args.sDacload.ucMisc = 0;
1073 
1074 	if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1
1075 		|| encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) {
1076 		args.sDacload.ucDacType = ATOM_DAC_A;
1077 	} else {
1078 		args.sDacload.ucDacType = ATOM_DAC_B;
1079 	}
1080 
1081 	if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1082 		args.sDacload.usDeviceID
1083 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT);
1084 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1085 
1086 		uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1087 
1088 		if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
1089 			return true;
1090 
1091 	} else if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1092 		args.sDacload.usDeviceID
1093 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT);
1094 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1095 
1096 		uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1097 
1098 		if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
1099 			return true;
1100 
1101 	} else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1102 		args.sDacload.usDeviceID
1103 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT);
1104 		if (tableMinor >= 3)
1105 			args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1106 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1107 
1108 		uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1109 
1110 		if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
1111 			return true;
1112 
1113 	} else if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1114 		args.sDacload.usDeviceID
1115 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT);
1116 		if (tableMinor >= 3)
1117 			args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1118 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1119 
1120 		uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1121 
1122 		if ((biosScratch0
1123 			& (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) {
1124 			return true; /* Composite connected */
1125 		} else if ((biosScratch0
1126 			& (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) {
1127 			return true; /* S-Video connected */
1128 		}
1129 
1130 	}
1131 	return false;
1132 }
1133 
1134 
1135 bool
1136 encoder_dig_load_detect(uint32 connectorIndex)
1137 {
1138 	TRACE("%s\n", __func__);
1139 	radeon_shared_info &info = *gInfo->shared_info;
1140 
1141 	if (info.dceMajor < 4) {
1142 		ERROR("%s: Strange: External DIG encoder on DCE < 4?\n", __func__);
1143 		return false;
1144 	}
1145 
1146 	encoder_external_setup(connectorIndex,
1147 		EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
1148 
1149 	uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1150 
1151 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1152 
1153 	if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0)
1154 		if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
1155 			return true;
1156 	if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0)
1157 		if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
1158 			return true;
1159 	if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1160 		if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
1161 			return true;
1162 	if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1163 		if ((biosScratch0
1164 			& (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0)
1165 			return true; /* Composite connected */
1166 		else if ((biosScratch0
1167 			& (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0)
1168 			return true; /* S-Video connected */
1169 	}
1170 
1171 	return false;
1172 }
1173 
1174 
1175 status_t
1176 transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
1177 	uint8 laneNumber, uint8 laneSet, int command)
1178 {
1179 	TRACE("%s\n", __func__);
1180 
1181 	uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1182 	int index;
1183 	switch (encoderID) {
1184 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1185 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1186 			break;
1187 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1188 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1189 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1190 			index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1191 			break;
1192 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1193 			index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
1194 			break;
1195 		default:
1196 			ERROR("%s: BUG: dig setup run on non-dig encoder!\n", __func__);
1197 			return B_ERROR;
1198 	}
1199 
1200 	if (index < 0) {
1201 		ERROR("%s: GetIndexIntoMasterTable failed!\n", __func__);
1202 		return B_ERROR;
1203 	}
1204 
1205 	uint8 tableMajor;
1206 	uint8 tableMinor;
1207 
1208 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
1209 		!= B_OK)
1210 		return B_ERROR;
1211 
1212 	// Prepare AtomBIOS arguments
1213 	union digTransmitterControl {
1214 		DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
1215 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
1216 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
1217 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
1218 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
1219 	};
1220 	union digTransmitterControl args;
1221 	memset(&args, 0, sizeof(args));
1222 
1223 	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
1224 		tableMajor, tableMinor);
1225 
1226 	int connectorObjectID
1227 		= (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
1228 			>> OBJECT_ID_SHIFT;
1229 	uint32 encoderObjectID = gConnector[connectorIndex]->encoder.objectID;
1230 	uint32 digEncoderID = encoder_pick_dig(connectorIndex);
1231 
1232 	pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
1233 
1234 	bool isDP = connector_is_dp(connectorIndex);
1235 	bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
1236 		== GRAPH_OBJECT_ENUM_ID2 ? true : false;
1237 
1238 	dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
1239 
1240 	uint32 dpClock = 0;
1241 	int dpLaneCount = 0;
1242 	if (dpInfo->valid == true) {
1243 		dpClock = dpInfo->linkRate;
1244 		dpLaneCount = dpInfo->laneCount;
1245 	}
1246 
1247 	switch (tableMajor) {
1248 		case 1:
1249 			switch (tableMinor) {
1250 				case 1:
1251 					args.v1.ucAction = command;
1252 					if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1253 						args.v1.usInitInfo
1254 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1255 					} else if (command
1256 						== ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1257 						args.v1.asMode.ucLaneSel = laneNumber;
1258 						args.v1.asMode.ucLaneSet = laneSet;
1259 					} else {
1260 						if (isDP) {
1261 							args.v1.usPixelClock
1262 								= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1263 						} else if (pixelClock > 165000) {
1264 							args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1265 								(pixelClock / 2) / 10);
1266 						} else {
1267 							args.v1.usPixelClock
1268 								= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1269 						}
1270 					}
1271 
1272 					args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1273 
1274 					if (digEncoderID > 0) {
1275 						args.v1.ucConfig
1276 							|= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
1277 					} else {
1278 						args.v1.ucConfig
1279 							|= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1280 					}
1281 
1282 					// TODO: IGP DIG Transmitter setup
1283 					#if 0
1284 					if ((rdev->flags & RADEON_IS_IGP) && (encoderObjectID
1285 						== ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1286 						if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
1287 							if (igp_lane_info & 0x1)
1288 								args.v1.ucConfig
1289 									|= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
1290 							else if (igp_lane_info & 0x2)
1291 								args.v1.ucConfig
1292 									|= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
1293 							else if (igp_lane_info & 0x4)
1294 								args.v1.ucConfig
1295 									|= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
1296 							else if (igp_lane_info & 0x8)
1297 								args.v1.ucConfig
1298 									|= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1299 						} else {
1300 							if (igp_lane_info & 0x3)
1301 								args.v1.ucConfig
1302 									|= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
1303 							else if (igp_lane_info & 0xc)
1304 								args.v1.ucConfig
1305 									|= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1306 						}
1307 					}
1308 					#endif
1309 
1310 					if (linkB == true)
1311 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
1312 					else
1313 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
1314 
1315 					if (isDP)
1316 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1317 					else if ((gConnector[connectorIndex]->flags
1318 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1319 						if (1) {
1320 							// if coherentMode, i've only ever seen it true
1321 							args.v1.ucConfig
1322 								|= ATOM_TRANSMITTER_CONFIG_COHERENT;
1323 						}
1324 						if (pixelClock > 165000) {
1325 							args.v1.ucConfig
1326 								|= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1327 						}
1328 					}
1329 					break;
1330 				case 2:
1331 					args.v2.ucAction = command;
1332 					if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1333 						args.v2.usInitInfo
1334 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1335 					} else if (command
1336 						== ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1337 						args.v2.asMode.ucLaneSel = laneNumber;
1338 						args.v2.asMode.ucLaneSet = laneSet;
1339 					} else {
1340 						if (isDP) {
1341 							args.v2.usPixelClock
1342 								= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1343 						} else if (pixelClock > 165000) {
1344 							args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1345 								(pixelClock / 2) / 10);
1346 						} else {
1347 							args.v2.usPixelClock
1348 								= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1349 						}
1350 					}
1351 					args.v2.acConfig.ucEncoderSel = digEncoderID;
1352 					if (linkB)
1353 						args.v2.acConfig.ucLinkSel = 1;
1354 
1355 					switch (encoderObjectID) {
1356 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1357 							args.v2.acConfig.ucTransmitterSel = 0;
1358 							break;
1359 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1360 							args.v2.acConfig.ucTransmitterSel = 1;
1361 							break;
1362 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1363 							args.v2.acConfig.ucTransmitterSel = 2;
1364 							break;
1365 					}
1366 
1367 					if (isDP) {
1368 						args.v2.acConfig.fCoherentMode = 1;
1369 						args.v2.acConfig.fDPConnector = 1;
1370 					} else if ((gConnector[connectorIndex]->flags
1371 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1372 						if (1) {
1373 							// if coherentMode, i've only ever seen it true
1374 							args.v2.acConfig.fCoherentMode = 1;
1375 						}
1376 
1377 						if (pixelClock > 165000)
1378 							args.v2.acConfig.fDualLinkConnector = 1;
1379 					}
1380 					break;
1381 				case 3:
1382 					args.v3.ucAction = command;
1383 					if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1384 						args.v3.usInitInfo
1385 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1386 					} else if (command
1387 						== ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1388 						args.v3.asMode.ucLaneSel = laneNumber;
1389 						args.v3.asMode.ucLaneSet = laneSet;
1390 					} else {
1391 						if (isDP) {
1392 							args.v3.usPixelClock
1393 								= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1394 						} else if (pixelClock > 165000) {
1395 							args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1396 								(pixelClock / 2) / 10);
1397 						} else {
1398 							args.v3.usPixelClock
1399 								= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1400 						}
1401 					}
1402 
1403 					if (isDP)
1404 						args.v3.ucLaneNum = dpLaneCount;
1405 					else if (pixelClock > 165000)
1406 						args.v3.ucLaneNum = 8;
1407 					else
1408 						args.v3.ucLaneNum = 4;
1409 
1410 					if (linkB == true)
1411 						args.v3.acConfig.ucLinkSel = 1;
1412 					if (digEncoderID & 1)
1413 						args.v3.acConfig.ucEncoderSel = 1;
1414 
1415 					// Select the PLL for the PHY
1416 					// DP PHY to be clocked from external src if possible
1417 
1418 					// DCE4 has external DCPLL clock for DP
1419 					if (isDP && gInfo->dpExternalClock) {
1420 						// use external clock source (id'ed to 2 on DCE4)
1421 						args.v3.acConfig.ucRefClkSource = 2; // EXT clock
1422 					} else
1423 						args.v3.acConfig.ucRefClkSource = pll->id;
1424 
1425 					switch (encoderObjectID) {
1426 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1427 							args.v3.acConfig.ucTransmitterSel = 0;
1428 							break;
1429 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1430 							args.v3.acConfig.ucTransmitterSel = 1;
1431 							break;
1432 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1433 							args.v3.acConfig.ucTransmitterSel = 2;
1434 							break;
1435 					}
1436 
1437 					if (isDP)
1438 						args.v3.acConfig.fCoherentMode = 1;
1439 					else if ((gConnector[connectorIndex]->flags
1440 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1441 						if (1) {
1442 							// if coherentMode, i've only ever seen it true
1443 							args.v3.acConfig.fCoherentMode = 1;
1444 						}
1445 						if (pixelClock > 165000)
1446 							args.v3.acConfig.fDualLinkConnector = 1;
1447 					}
1448 					break;
1449 				case 4:
1450 					args.v4.ucAction = command;
1451 					if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1452 						args.v4.usInitInfo
1453 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1454 					} else if (command
1455 						== ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1456 						args.v4.asMode.ucLaneSel = laneNumber;
1457 						args.v4.asMode.ucLaneSet = laneSet;
1458 					} else {
1459 						if (isDP) {
1460 							args.v4.usPixelClock
1461 								= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1462 						} else if (pixelClock > 165000) {
1463 							args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1464 								(pixelClock / 2) / 10);
1465 						} else {
1466 							args.v4.usPixelClock
1467 								= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1468 						}
1469 					}
1470 
1471 					if (isDP)
1472 						args.v4.ucLaneNum = dpLaneCount;
1473 					else if (pixelClock > 165000)
1474 						args.v4.ucLaneNum = 8;
1475 					else
1476 						args.v4.ucLaneNum = 4;
1477 
1478 					if (linkB == true)
1479 						args.v4.acConfig.ucLinkSel = 1;
1480 					if (digEncoderID & 1)
1481 						args.v4.acConfig.ucEncoderSel = 1;
1482 
1483 					// Select the PLL for the PHY
1484 					// DP PHY to be clocked from external src if possible
1485 					// DCE5, DCPLL usually generates the DP ref clock
1486 					if (isDP) {
1487 						if (gInfo->dpExternalClock > 0) {
1488 							args.v4.acConfig.ucRefClkSource
1489 								= ENCODER_REFCLK_SRC_EXTCLK;
1490 						} else {
1491 							args.v4.acConfig.ucRefClkSource
1492 								= ENCODER_REFCLK_SRC_DCPLL;
1493 						}
1494 					} else
1495 						args.v4.acConfig.ucRefClkSource = pll->id;
1496 
1497 					switch (encoderObjectID) {
1498 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1499 							args.v4.acConfig.ucTransmitterSel = 0;
1500 							break;
1501 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1502 							args.v4.acConfig.ucTransmitterSel = 1;
1503 							break;
1504 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1505 							args.v4.acConfig.ucTransmitterSel = 2;
1506 							break;
1507 					}
1508 
1509 					if (isDP)
1510 						args.v4.acConfig.fCoherentMode = 1;
1511 					else if ((gConnector[connectorIndex]->flags
1512 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1513 						if (1) {
1514 							// if coherentMode, i've only ever seen it true
1515 							args.v4.acConfig.fCoherentMode = 1;
1516 						}
1517 						if (pixelClock > 165000)
1518 							args.v4.acConfig.fDualLinkConnector = 1;
1519 					}
1520 					break;
1521 				case 5:
1522 					args.v5.ucAction = command;
1523 
1524 					if (isDP) {
1525 						args.v5.usSymClock
1526 							= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1527 					} else {
1528 						args.v5.usSymClock
1529 							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1530 					}
1531 					switch (encoderObjectID) {
1532 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1533 							if (linkB)
1534 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1535 							else
1536 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1537 							break;
1538 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1539 							if (linkB)
1540 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1541 							else
1542 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1543 							break;
1544 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1545 							if (linkB)
1546 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1547 							else
1548 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1549 							break;
1550 					}
1551 					if (isDP) {
1552 						args.v5.ucLaneNum = dpLaneCount;
1553 					} else if (pixelClock >= 165000) {
1554 						args.v5.ucLaneNum = 8;
1555 					} else {
1556 						args.v5.ucLaneNum = 4;
1557 					}
1558 
1559 					args.v5.ucConnObjId = connectorObjectID;
1560 					args.v5.ucDigMode
1561 						= display_get_encoder_mode(connectorIndex);
1562 
1563 					if (isDP && gInfo->dpExternalClock) {
1564 						args.v5.asConfig.ucPhyClkSrcId
1565 							= ENCODER_REFCLK_SRC_EXTCLK;
1566 					} else {
1567 						args.v5.asConfig.ucPhyClkSrcId = pll->id;
1568 					}
1569 
1570 					if (isDP) {
1571 						args.v5.asConfig.ucCoherentMode = 1;
1572 							// DP always coherent
1573 					} else if ((gConnector[connectorIndex]->flags
1574 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1575 						// TODO: dig coherent mode? VVV
1576 						args.v5.asConfig.ucCoherentMode = 1;
1577 					}
1578 
1579 					// RADEON_HPD_NONE? VVV
1580 					args.v5.asConfig.ucHPDSel = 0;
1581 
1582 					args.v5.ucDigEncoderSel = 1 << digEncoderID;
1583 					args.v5.ucDPLaneSet = laneSet;
1584 					break;
1585 				default:
1586 					ERROR("%s: unknown table version\n", __func__);
1587 			}
1588 			break;
1589 		default:
1590 			ERROR("%s: unknown table version\n", __func__);
1591 	}
1592 
1593 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
1594 }
1595 
1596 
1597 void
1598 encoder_crtc_scratch(uint8 crtcID)
1599 {
1600 	TRACE("%s\n", __func__);
1601 
1602 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1603 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1604 
1605 	// TODO: r500
1606 	uint32 biosScratch3 = Read32(OUT, R600_SCRATCH_REG3);
1607 
1608 	if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1609 		biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE;
1610 		biosScratch3 |= (crtcID << 18);
1611 	}
1612 	if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1613 		biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE;
1614 		biosScratch3 |= (crtcID << 24);
1615 	}
1616 	if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1617 		biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
1618 		biosScratch3 |= (crtcID << 16);
1619 	}
1620 	if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1621 		biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
1622 		biosScratch3 |= (crtcID << 20);
1623 	}
1624 	if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
1625 		biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
1626 		biosScratch3 |= (crtcID << 17);
1627 	}
1628 	if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
1629 		biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
1630 		biosScratch3 |= (crtcID << 19);
1631 	}
1632 	if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
1633 		biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
1634 		biosScratch3 |= (crtcID << 23);
1635 	}
1636 	if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
1637 		biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
1638 		biosScratch3 |= (crtcID << 25);
1639 	}
1640 
1641 	// TODO: r500
1642 	Write32(OUT, R600_SCRATCH_REG3, biosScratch3);
1643 }
1644 
1645 
1646 void
1647 encoder_dpms_scratch(uint8 crtcID, bool power)
1648 {
1649 	TRACE("%s\n", __func__);
1650 
1651 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1652 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1653 
1654 	// TODO: r500
1655 	uint32 biosScratch2 = Read32(OUT, R600_SCRATCH_REG2);
1656 
1657 	if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1658 		if (power == true)
1659 			biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE;
1660 		else
1661 			biosScratch2 |= ATOM_S2_TV1_DPMS_STATE;
1662 	}
1663 	if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1664 		if (power == true)
1665 			biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE;
1666 		else
1667 			biosScratch2 |= ATOM_S2_CV_DPMS_STATE;
1668 	}
1669 	if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1670 		if (power == true)
1671 			biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE;
1672 		else
1673 			biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE;
1674 	}
1675 	if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1676 		if (power == true)
1677 			biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE;
1678 		else
1679 			biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE;
1680 	}
1681 	if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
1682 		if (power == true)
1683 			biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE;
1684 		else
1685 			biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE;
1686 	}
1687 	if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
1688 		if (power == true)
1689 			biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE;
1690 		else
1691 			biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE;
1692 	}
1693 	if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
1694 		if (power == true)
1695 			biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE;
1696 		else
1697 			biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE;
1698 	}
1699 	if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
1700 		if (power == true)
1701 			biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE;
1702 		else
1703 			biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE;
1704 	}
1705 	if ((connectorFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) {
1706 		if (power == true)
1707 			biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE;
1708 		else
1709 			biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE;
1710 	}
1711 	if ((connectorFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) {
1712 		if (power == true)
1713 			biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE;
1714 		else
1715 			biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE;
1716 	}
1717 	Write32(OUT, R600_SCRATCH_REG2, biosScratch2);
1718 }
1719 
1720 
1721 void
1722 encoder_dpms_set(uint8 crtcID, int mode)
1723 {
1724 	TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false");
1725 
1726 	int index = -1;
1727 	radeon_shared_info &info = *gInfo->shared_info;
1728 
1729 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1730 	memset(&args, 0, sizeof(args));
1731 
1732 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1733 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1734 	uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1735 
1736 	switch (encoderID) {
1737 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1738 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1739 			index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1740 			break;
1741 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1742 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1743 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1744 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1745 			encoder_dpms_set_dig(crtcID, mode);
1746 			break;
1747 		case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1748 		case ENCODER_OBJECT_ID_INTERNAL_DDI:
1749 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1750 			break;
1751 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1752 			if (info.dceMajor >= 5)
1753 				encoder_dpms_set_dvo(crtcID, mode);
1754 			else if (info.dceMajor >= 3)
1755 				encoder_dpms_set_dig(crtcID, mode);
1756 			else
1757 				index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1758 			break;
1759 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1760 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1761 			break;
1762 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1763 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
1764 				index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1765 			else
1766 				index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1767 			break;
1768 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1769 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1770 			if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
1771 				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1772 			else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1773 				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1774 			else
1775 				index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1776 			break;
1777 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1778 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1779 			if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
1780 				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1781 			else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1782 				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1783 			else
1784 				index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1785 			break;
1786 		// default, none on purpose
1787 	}
1788 
1789 	// If we have an index, we need to execute a table.
1790 	if (index >= 0) {
1791 		switch (mode) {
1792 			case B_DPMS_ON:
1793 				args.ucAction = ATOM_ENABLE;
1794 				break;
1795 			case B_DPMS_STAND_BY:
1796 			case B_DPMS_SUSPEND:
1797 			case B_DPMS_OFF:
1798 				args.ucAction = ATOM_DISABLE;
1799 				break;
1800 		}
1801 
1802 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1803 		if (info.dceMajor < 5) {
1804 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1805 				args.ucAction = args.ucAction == ATOM_DISABLE
1806 					? ATOM_LCD_BLOFF : ATOM_LCD_BLON;
1807 				atom_execute_table(gAtomContext, index, (uint32*)&args);
1808 			}
1809 			encoder_dpms_scratch(crtcID, true);
1810 		}
1811 	}
1812 
1813 	// If an external encoder exists, we should flip it on as well
1814 	if (gConnector[connectorIndex]->encoderExternal.valid == true)
1815 		encoder_dpms_set_external(crtcID, mode);
1816 }
1817 
1818 
1819 void
1820 encoder_dpms_set_dig(uint8 crtcID, int mode)
1821 {
1822 	TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false");
1823 
1824 	radeon_shared_info &info = *gInfo->shared_info;
1825 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1826 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1827 	pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
1828 
1829 	switch (mode) {
1830 		case B_DPMS_ON:
1831 			if (info.chipsetID == RADEON_RV710
1832 				|| info.chipsetID == RADEON_RV730
1833 				|| (info.chipsetFlags & CHIP_APU) != 0
1834 				|| info.dceMajor >= 5) {
1835 				if (info.dceMajor >= 6) {
1836 					/*	We need to call CMD_SETUP before reenabling the encoder,
1837 						otherwise we never get a picture */
1838 					transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1839 						ATOM_ENCODER_CMD_SETUP);
1840 				}
1841 				encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_ENABLE);
1842 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1843 					ATOM_TRANSMITTER_ACTION_SETUP);
1844 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1845 					ATOM_TRANSMITTER_ACTION_ENABLE);
1846 				/* some early dce3.2 boards have a bug in their transmitter
1847 				   control table */
1848 				if (info.chipsetID != RADEON_RV710
1849 					&& info.chipsetID != RADEON_RV730)
1850 					transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1851 						ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
1852 			} else {
1853 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1854 					ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
1855 			}
1856 			if (connector_is_dp(connectorIndex)) {
1857 				if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) {
1858 					ERROR("%s: TODO, edp_panel_power for this card!\n",
1859 						__func__);
1860 					// atombios_set_edp_panel_power(connector,
1861 					//	ATOM_TRANSMITTER_ACTION_POWER_ON);
1862 				}
1863 				if (info.dceMajor >= 4) {
1864 					encoder_dig_setup(connectorIndex, pll->pixelClock,
1865 						ATOM_ENCODER_CMD_DP_VIDEO_OFF);
1866 				}
1867 				// dp link train
1868 				dp_link_train(crtcID);
1869 				if (info.dceMajor >= 4) {
1870 					encoder_dig_setup(connectorIndex, pll->pixelClock,
1871 						ATOM_ENCODER_CMD_DP_VIDEO_ON);
1872 				}
1873 				// not sure what AtomBIOS table/command sets this
1874 				// register, but it's required to get the video output
1875 				Write32(OUT, AVIVO_DP_VID_STREAM_CNTL, 0x201);
1876 			}
1877 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1878 				transmitter_dig_setup(connectorIndex, pll->pixelClock,
1879 					0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON);
1880 			}
1881 			break;
1882 		case B_DPMS_STAND_BY:
1883 		case B_DPMS_SUSPEND:
1884 		case B_DPMS_OFF:
1885 			if ((info.chipsetFlags & CHIP_APU) != 0 || info.dceMajor >= 5) {
1886 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1887 					ATOM_TRANSMITTER_ACTION_DISABLE);
1888 			} else {
1889 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1890 					ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT);
1891 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1892 					ATOM_TRANSMITTER_ACTION_DISABLE);
1893 				encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_DISABLE);
1894 			}
1895 			if (connector_is_dp(connectorIndex)) {
1896 				if (info.dceMajor >= 4) {
1897 					encoder_dig_setup(connectorIndex, pll->pixelClock,
1898 						ATOM_ENCODER_CMD_DP_VIDEO_OFF);
1899 					#if 0
1900 					if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1901 						atombios_set_edp_panel_power(connector,
1902 							ATOM_TRANSMITTER_ACTION_POWER_OFF);
1903 						radeon_dig_connector->edp_on = false;
1904 					#endif
1905 				}
1906 			}
1907 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1908 				transmitter_dig_setup(connectorIndex, pll->pixelClock,
1909 					0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF);
1910 			}
1911 			break;
1912 	}
1913 }
1914 
1915 
1916 void
1917 encoder_dpms_set_external(uint8 crtcID, int mode)
1918 {
1919 	TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false");
1920 
1921 	radeon_shared_info &info = *gInfo->shared_info;
1922 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1923 
1924 	switch (mode) {
1925 		case B_DPMS_ON:
1926 			if ((info.chipsetFlags & CHIP_APU) != 0) {
1927 				encoder_external_setup(connectorIndex,
1928 					EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
1929 				encoder_external_setup(connectorIndex,
1930 					EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
1931 			} else
1932 				encoder_external_setup(connectorIndex, ATOM_ENABLE);
1933 
1934 			break;
1935 		case B_DPMS_STAND_BY:
1936 		case B_DPMS_SUSPEND:
1937 		case B_DPMS_OFF:
1938 			if ((info.chipsetFlags & CHIP_APU) != 0) {
1939 				encoder_external_setup(connectorIndex,
1940 					EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
1941 				encoder_external_setup(connectorIndex,
1942 					EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
1943 			} else
1944 				encoder_external_setup(connectorIndex, ATOM_DISABLE);
1945 
1946 			break;
1947 	}
1948 }
1949 
1950 
1951 void
1952 encoder_dpms_set_dvo(uint8 crtcID, int mode)
1953 {
1954 	ERROR("%s: TODO, dvo encoder dpms stub\n", __func__);
1955 }
1956 
1957 
1958 void
1959 encoder_output_lock(bool lock)
1960 {
1961 	TRACE("%s: %s\n", __func__, lock ? "true" : "false");
1962 	uint32 biosScratch6 = Read32(OUT, R600_SCRATCH_REG6);
1963 
1964 	if (lock) {
1965 		biosScratch6 |= ATOM_S6_CRITICAL_STATE;
1966 		biosScratch6 &= ~ATOM_S6_ACC_MODE;
1967 	} else {
1968 		biosScratch6 &= ~ATOM_S6_CRITICAL_STATE;
1969 		biosScratch6 |= ATOM_S6_ACC_MODE;
1970 	}
1971 
1972 	Write32(OUT, R600_SCRATCH_REG6, biosScratch6);
1973 }
1974 
1975 static const char* encoder_name_matrix[] = {
1976 	"NONE",
1977 	"Internal Radeon LVDS",
1978 	"Internal Radeon TMDS1",
1979 	"Internal Radeon TMDS2",
1980 	"Internal Radeon DAC1",
1981 	"Internal Radeon DAC2 (TV)",
1982 	"Internal Radeon SDVOA",
1983 	"Internal Radeon SDVOB",
1984 	"External 3rd party SI170B",
1985 	"External 3rd party CH7303",
1986 	"External 3rd party CH7301",
1987 	"Internal Radeon DVO1",
1988 	"External 3rd party SDVOA",
1989 	"External 3rd party SDVOB",
1990 	"External 3rd party TITFP513",
1991 	"Internal LVTM1",
1992 	"External 3rd party VT1623",
1993 	"External HDMI SI1930",
1994 	"Internal HDMI",
1995 	"Internal Kaleidoscope TMDS1",
1996 	"Internal Kaleidoscope DVO1",
1997 	"Internal Kaleidoscope DAC1",
1998 	"Internal Kaleidoscope DAC2",
1999 	"External Kaleidoscope SI178",
2000 	"MVPU FPGA",
2001 	"Internal Kaleidoscope DDI",
2002 	"External Kaleidoscope VT1625",
2003 	"External Kaleidoscope HDMI SI1932",
2004 	"External Kaleidoscope DP AN9801",
2005 	"External Kaleidoscope DP DP501",
2006 	"Internal Kaleidoscope UNIPHY",
2007 	"Internal Kaleidoscope LVTMA",
2008 	"Internal Kaleidoscope UNIPHY1",
2009 	"Internal Kaleidoscope UNIPHY2",
2010 	"External Nutmeg Bridge",
2011 	"External Travis Bridge",
2012 	"Internal Kaleidoscope VCE"
2013 };
2014 
2015 
2016 const char*
2017 encoder_name_lookup(uint32 encoderID) {
2018 	if (encoderID < B_COUNT_OF(encoder_name_matrix))
2019 		return encoder_name_matrix[encoderID];
2020 	else
2021 		return "Unknown";
2022 }
2023 
2024 
2025 uint32
2026 encoder_object_lookup(uint32 connectorFlags, uint8 dacID)
2027 {
2028 	// used on older cards to take a guess at the encoder
2029 	// object
2030 
2031 	radeon_shared_info &info = *gInfo->shared_info;
2032 
2033 	uint32 ret = 0;
2034 
2035 	switch (connectorFlags) {
2036 		case ATOM_DEVICE_CRT1_SUPPORT:
2037 		case ATOM_DEVICE_TV1_SUPPORT:
2038 		case ATOM_DEVICE_TV2_SUPPORT:
2039 		case ATOM_DEVICE_CRT2_SUPPORT:
2040 		case ATOM_DEVICE_CV_SUPPORT:
2041 			switch (dacID) {
2042 				case 1:
2043 					if ((info.chipsetID == RADEON_RS400)
2044 						|| (info.chipsetID == RADEON_RS480))
2045 						ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
2046 					else if (info.chipsetID >= RADEON_RS600)
2047 						ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
2048 					else
2049 						ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
2050 					break;
2051 				case 2:
2052 					if (info.chipsetID >= RADEON_RS600)
2053 						ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
2054 					else {
2055 						ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
2056 					}
2057 					break;
2058 				case 3: // external dac
2059 					if (info.chipsetID >= RADEON_RS600)
2060 						ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
2061 					else
2062 						ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2063 					break;
2064 			}
2065 			break;
2066 		case ATOM_DEVICE_LCD1_SUPPORT:
2067 			if (info.chipsetID >= RADEON_RS600)
2068 				ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
2069 			else
2070 				ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
2071 			break;
2072 		case ATOM_DEVICE_DFP1_SUPPORT:
2073 			if ((info.chipsetID == RADEON_RS400)
2074 				|| (info.chipsetID == RADEON_RS480))
2075 				ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2076 			else if (info.chipsetID >= RADEON_RS600)
2077 				ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
2078 			else
2079 				ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
2080 			break;
2081 		case ATOM_DEVICE_LCD2_SUPPORT:
2082 		case ATOM_DEVICE_DFP2_SUPPORT:
2083 			if ((info.chipsetID == RADEON_RS600)
2084 				|| (info.chipsetID == RADEON_RS690)
2085 				|| (info.chipsetID == RADEON_RS740))
2086 				ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
2087 			else if (info.chipsetID >= RADEON_RS600)
2088 				ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
2089 			else
2090 				ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2091 			break;
2092 		case ATOM_DEVICE_DFP3_SUPPORT:
2093 			ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
2094 			break;
2095 	}
2096 
2097 	return ret;
2098 }
2099 
2100 
2101 uint32
2102 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags)
2103 {
2104 	switch (encoderID) {
2105 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2106 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2107 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2108 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2109 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2110 				return VIDEO_ENCODER_LVDS;
2111 			else
2112 				return VIDEO_ENCODER_TMDS;
2113 			break;
2114 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2115 			return VIDEO_ENCODER_DAC;
2116 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2117 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2118 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2119 			return VIDEO_ENCODER_TVDAC;
2120 		case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2121 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2122 		case ENCODER_OBJECT_ID_INTERNAL_DDI:
2123 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2124 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2125 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2126 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2127 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2128 				return VIDEO_ENCODER_LVDS;
2129 			else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
2130 				return VIDEO_ENCODER_DAC;
2131 			else
2132 				return VIDEO_ENCODER_TMDS;
2133 			break;
2134 		case ENCODER_OBJECT_ID_SI170B:
2135 		case ENCODER_OBJECT_ID_CH7303:
2136 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2137 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2138 		case ENCODER_OBJECT_ID_TITFP513:
2139 		case ENCODER_OBJECT_ID_VT1623:
2140 		case ENCODER_OBJECT_ID_HDMI_SI1930:
2141 		case ENCODER_OBJECT_ID_TRAVIS:
2142 		case ENCODER_OBJECT_ID_NUTMEG:
2143 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2144 				return VIDEO_ENCODER_LVDS;
2145 			else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
2146 				return VIDEO_ENCODER_DAC;
2147 			else
2148 				return VIDEO_ENCODER_TMDS;
2149 			break;
2150 	}
2151 
2152 	return VIDEO_ENCODER_NONE;
2153 }
2154 
2155 
2156 bool
2157 encoder_is_external(uint32 encoderID)
2158 {
2159 	switch (encoderID) {
2160 		case ENCODER_OBJECT_ID_SI170B:
2161 		case ENCODER_OBJECT_ID_CH7303:
2162 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2163 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2164 		case ENCODER_OBJECT_ID_TITFP513:
2165 		case ENCODER_OBJECT_ID_VT1623:
2166 		case ENCODER_OBJECT_ID_HDMI_SI1930:
2167 		case ENCODER_OBJECT_ID_TRAVIS:
2168 		case ENCODER_OBJECT_ID_NUTMEG:
2169 			return true;
2170 	}
2171 
2172 	return false;
2173 }
2174 
2175 
2176 bool
2177 encoder_is_dp_bridge(uint32 encoderID)
2178 {
2179 	switch (encoderID) {
2180 		case ENCODER_OBJECT_ID_TRAVIS:
2181 		case ENCODER_OBJECT_ID_NUTMEG:
2182 			return true;
2183 	}
2184 	return false;
2185 }
2186