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