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