xref: /haiku/src/add-ons/accelerants/radeon_hd/encoder.cpp (revision 1fe24d0cd0b547a771c00f6fca8f50ba6ca2fb2c)
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 "accelerant_protos.h"
11 #include "accelerant.h"
12 #include "bios.h"
13 #include "display.h"
14 #include "utility.h"
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <math.h>
20 
21 
22 #define TRACE_ENCODER
23 #ifdef TRACE_ENCODER
24 extern "C" void _sPrintf(const char *format, ...);
25 #   define TRACE(x...) _sPrintf("radeon_hd: " x)
26 #else
27 #   define TRACE(x...) ;
28 #endif
29 
30 #define ERROR(x...) _sPrintf("radeon_hd: " x)
31 
32 
33 union crtc_source_param {
34 	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
35 	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
36 };
37 
38 
39 void
40 encoder_assign_crtc(uint8 crtcID)
41 {
42 	TRACE("%s\n", __func__);
43 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
44 	union crtc_source_param args;
45 
46 	// Table version
47 	uint8 tableMajor;
48 	uint8 tableMinor;
49 
50 	memset(&args, 0, sizeof(args));
51 
52 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
53 		!= B_OK)
54 		return;
55 
56 	uint16 connectorIndex = gDisplay[crtcID]->connectorIndex;
57 	uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
58 	uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags;
59 
60 	switch (tableMajor) {
61 		case 1:
62 			switch (tableMinor) {
63 				case 1:
64 				default:
65 					args.v1.ucCRTC = crtcID;
66 					switch (encoderID) {
67 						case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
68 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
69 							args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
70 							break;
71 						case ENCODER_OBJECT_ID_INTERNAL_LVDS:
72 						case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
73 							if ((gConnector[connectorIndex]->flags
74 								& ATOM_DEVICE_LCD1_SUPPORT) != 0)
75 								args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
76 							else
77 								args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
78 							break;
79 						case ENCODER_OBJECT_ID_INTERNAL_DVO1:
80 						case ENCODER_OBJECT_ID_INTERNAL_DDI:
81 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
82 							args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
83 							break;
84 						case ENCODER_OBJECT_ID_INTERNAL_DAC1:
85 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
86 							if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) {
87 								args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
88 							} else if ((encoderFlags
89 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
90 								args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
91 							} else
92 								args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
93 							break;
94 						case ENCODER_OBJECT_ID_INTERNAL_DAC2:
95 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
96 							if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) {
97 								args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
98 							} else if ((encoderFlags
99 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
100 								args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
101 							} else
102 								args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
103 							break;
104 					}
105 					break;
106 				case 2:
107 					args.v2.ucCRTC = crtcID;
108 					args.v2.ucEncodeMode
109 						= display_get_encoder_mode(connectorIndex);
110 					switch (encoderID) {
111 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
112 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
113 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
114 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
115 							ERROR("%s: DIG encoder not yet supported!\n",
116 								__func__);
117 							//dig = radeon_encoder->enc_priv;
118 							//switch (dig->dig_encoder) {
119 							//	case 0:
120 							//		args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
121 							//		break;
122 							//	case 1:
123 							//		args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
124 							//		break;
125 							//	case 2:
126 							//		args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
127 							//		break;
128 							//	case 3:
129 							//		args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
130 							//		break;
131 							//	case 4:
132 							//		args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
133 							//		break;
134 							//	case 5:
135 							//		args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
136 							//		break;
137 							//}
138 							break;
139 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
140 							args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
141 							break;
142 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
143 							if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) {
144 								args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
145 							} else if ((encoderFlags
146 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
147 								args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
148 							} else
149 								args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
150 							break;
151 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
152 							if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) {
153 								args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
154 							} else if ((encoderFlags
155 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
156 								args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
157 							} else
158 								args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
159 							break;
160 					}
161 					break;
162 			}
163 			break;
164 		default:
165 			ERROR("%s: Unknown table version: %" B_PRIu8 ".%" B_PRIu8 "\n",
166 				__func__, tableMajor, tableMinor);
167 			return;
168 	}
169 
170 	atom_execute_table(gAtomContext, index, (uint32*)&args);
171 
172 	// update crtc encoder scratch register @ scratch 3
173 	encoder_crtc_scratch(crtcID);
174 }
175 
176 
177 void
178 encoder_apply_quirks(uint8 crtcID)
179 {
180 	TRACE("%s\n", __func__);
181 	radeon_shared_info &info = *gInfo->shared_info;
182 	register_info* regs = gDisplay[crtcID]->regs;
183 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
184 	uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags;
185 
186 	// Setting the scaler clears this on some chips...
187 	if (info.dceMajor >= 3
188 		&& (encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0) {
189 		// TODO: assume non interleave mode for now
190 		// en: EVERGREEN_INTERLEAVE_EN : AVIVO_D1MODE_INTERLEAVE_EN
191 		Write32(OUT, regs->modeDataFormat, 0);
192 	}
193 }
194 
195 
196 void
197 encoder_mode_set(uint8 id, uint32 pixelClock)
198 {
199 	TRACE("%s\n", __func__);
200 	radeon_shared_info &info = *gInfo->shared_info;
201 	uint32 connectorIndex = gDisplay[id]->connectorIndex;
202 	uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags;
203 
204 	switch (gConnector[connectorIndex]->encoder.objectID) {
205 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
206 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
207 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
208 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
209 			encoder_analog_setup(id, pixelClock, ATOM_ENABLE);
210 			if ((encoderFlags
211 				& (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) != 0) {
212 				encoder_tv_setup(id, pixelClock, ATOM_ENABLE);
213 			} else {
214 				encoder_tv_setup(id, pixelClock, ATOM_DISABLE);
215 			}
216 			break;
217 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
218 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
219 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
220 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
221 			encoder_digital_setup(id, pixelClock, PANEL_ENCODER_ACTION_ENABLE);
222 			break;
223 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
224 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
225 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
226 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
227 			if (info.dceMajor >= 4) {
228 				//atombios_dig_transmitter_setup(encoder,
229 				//	ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
230 					// TODO: Disable the dig transmitter
231 				encoder_dig_setup(id, pixelClock, ATOM_ENCODER_CMD_SETUP);
232 					// Setup and enable the dig encoder
233 
234 				//atombios_dig_transmitter_setup(encoder,
235 				//	ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
236 					// TODO: Enable the dig transmitter
237 			} else {
238 				//atombios_dig_transmitter_setup(encoder,
239 				//	ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
240 					// Disable the dig transmitter
241 				encoder_dig_setup(id, pixelClock, ATOM_DISABLE);
242 					// Disable the dig encoder
243 
244 				/* setup and enable the encoder and transmitter */
245 				encoder_dig_setup(id, pixelClock, ATOM_ENABLE);
246 					// Setup and enable the dig encoder
247 
248 				//atombios_dig_transmitter_setup(encoder,
249 				//	ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
250 				//atombios_dig_transmitter_setup(encoder,
251 				//	ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
252 					// TODO: Setup and Enable the dig transmitter
253 			}
254 
255 			TRACE("%s: TODO for DIG encoder setup\n", __func__);
256 			break;
257 		case ENCODER_OBJECT_ID_INTERNAL_DDI:
258 		case ENCODER_OBJECT_ID_INTERNAL_DVO1:
259 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
260 			TRACE("%s: TODO for DVO encoder setup\n", __func__);
261 			break;
262 		case ENCODER_OBJECT_ID_TRAVIS: // external DP -> LVDS encoder
263 		case ENCODER_OBJECT_ID_NUTMEG: // external DP -> VGA encoder
264 			ERROR("%s: Oh, you have a TRAVIS or NUTMEG DP external encoder..."
265 				" what a pitty.\n", __func__);
266 			// * PALM can have native LVDS / VGA, or have them wired via DP
267 			//   This is an OEM choice on PALM chipsets
268 			// * SUMO or SUMO2 *always* have LVDS or VGA connected through DP
269 			// fallthrough
270 		case ENCODER_OBJECT_ID_SI170B:
271 		case ENCODER_OBJECT_ID_CH7303:
272 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
273 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
274 		case ENCODER_OBJECT_ID_TITFP513:
275 		case ENCODER_OBJECT_ID_VT1623:
276 		case ENCODER_OBJECT_ID_HDMI_SI1930:
277 			if (info.dceMajor >= 4 && info.dceMinor >= 1) {
278 				encoder_external_setup(id, pixelClock,
279 					EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
280 			} else {
281 				encoder_external_setup(id, pixelClock,
282 					ATOM_ENABLE);
283 			}
284 			break;
285 		default:
286 			TRACE("%s: TODO for unknown encoder setup!\n", __func__);
287 	}
288 
289 	encoder_apply_quirks(id);
290 }
291 
292 
293 status_t
294 encoder_tv_setup(uint8 id, uint32 pixelClock, int command)
295 {
296 	uint32 connectorIndex = gDisplay[id]->connectorIndex;
297 	uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags;
298 
299 	TV_ENCODER_CONTROL_PS_ALLOCATION args;
300 	memset(&args, 0, sizeof(args));
301 
302 	int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
303 
304 	args.sTVEncoder.ucAction = command;
305 
306 	if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
307 		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
308 	else {
309 		// TODO: we assume NTSC for now
310 		args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
311 	}
312 
313 	args.sTVEncoder.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
314 
315 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
316 }
317 
318 
319 union lvds_encoder_control {
320 	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
321 	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
322 };
323 
324 
325 status_t
326 encoder_digital_setup(uint8 id, uint32 pixelClock, int command)
327 {
328 	TRACE("%s\n", __func__);
329 
330 	uint32 connectorIndex = gDisplay[id]->connectorIndex;
331 
332 	union lvds_encoder_control args;
333 	memset(&args, 0, sizeof(args));
334 
335 	int index = 0;
336 	uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags;
337 
338 	switch (gConnector[connectorIndex]->encoder.objectID) {
339 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
340 			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
341 			break;
342 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
343 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
344 			index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
345 			break;
346 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
347 			if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
348 				index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
349 			else
350 				index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
351 			break;
352 	}
353 
354 	// Table verson
355 	uint8 tableMajor;
356 	uint8 tableMinor;
357 
358 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
359 		!= B_OK) {
360 		ERROR("%s: cannot parse command table\n", __func__);
361 		return B_ERROR;
362 	}
363 
364 	switch (tableMajor) {
365 	case 1:
366 	case 2:
367 		switch (tableMinor) {
368 			case 1:
369 				args.v1.ucMisc = 0;
370 				args.v1.ucAction = command;
371 				if (0)	// TODO: HDMI?
372 					args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
373 				args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
374 
375 				if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
376 					// TODO: laptop display support
377 					//if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
378 					//	args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
379 					//if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
380 					//	args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
381 				} else {
382 					//if (dig->linkb)
383 					//	args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
384 					if (pixelClock > 165000)
385 						args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
386 					/*if (pScrn->rgbBits == 8) */
387 					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
388 				}
389 				break;
390 			case 2:
391 			case 3:
392 				args.v2.ucMisc = 0;
393 				args.v2.ucAction = command;
394 				if (tableMinor == 3) {
395 					//if (dig->coherent_mode)
396 					//	args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
397 				}
398 				if (0) // TODO: HDMI?
399 					args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
400 				args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
401 				args.v2.ucTruncate = 0;
402 				args.v2.ucSpatial = 0;
403 				args.v2.ucTemporal = 0;
404 				args.v2.ucFRC = 0;
405 				if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
406 					// TODO: laptop display support
407 					//if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
408 					//	args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
409 					//if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
410 					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
411 					//if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
412 					//	args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
413 					//}
414 					//if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
415 					//	args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
416 					//	if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) {
417 					//		args.v2.ucTemporal
418 					//			|= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
419 					//	}
420 					//	if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT)
421 					//		& 0x3) == 2) {
422 					//		args.v2.ucTemporal
423 					//			|= PANEL_ENCODER_TEMPORAL_LEVEL_4;
424 					//	}
425 					//}
426 				} else {
427 					//if (dig->linkb)
428 					//	args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
429 					if (pixelClock > 165000)
430 						args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
431 				}
432 				break;
433 			default:
434 				ERROR("%s: Unknown minor table version: %"
435 					B_PRIu8 ".%" B_PRIu8 "\n", __func__,
436 					tableMajor, tableMinor);
437 				return B_ERROR;
438 		}
439 		break;
440 	default:
441 		ERROR("%s: Unknown major table version: %" B_PRIu8 ".%" B_PRIu8 "\n",
442 			__func__, tableMajor, tableMinor);
443 		return B_ERROR;
444 	}
445 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
446 }
447 
448 
449 union dig_encoder_control {
450 	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
451 	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
452 	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
453 	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
454 };
455 
456 
457 status_t
458 encoder_dig_setup(uint8 id, uint32 pixelClock, int command)
459 {
460 	radeon_shared_info &info = *gInfo->shared_info;
461 
462 	uint32 connectorIndex = gDisplay[id]->connectorIndex;
463 	uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
464 
465 	union dig_encoder_control args;
466 	int index = 0;
467 
468 	// Table verson
469 	uint8 tableMajor;
470 	uint8 tableMinor;
471 
472 	memset(&args, 0, sizeof(args));
473 
474 	if (info.dceMajor > 4)
475 		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
476 	else {
477 		if (1) // TODO: pick dig encoder
478 			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
479 		else
480 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
481 	}
482 
483 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
484 		!= B_OK) {
485 		ERROR("%s: cannot parse command table\n", __func__);
486 		return B_ERROR;
487 	}
488 
489 	args.v1.ucAction = command;
490 	args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
491 
492 	#if 0
493 	if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) {
494 		if (info.dceMajor >= 4 && 0) // TODO: 0 == if DP bridge
495 			args.v3.ucPanelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
496 		else
497 			args.v3.ucPanelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
498 	} else {
499 		args.v1.ucEncoderMode = display_get_encoder_mode(connectorIndex);
500 
501 	if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
502 		|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
503 		args.v1.ucLaneNum = dp_lane_count;
504 	} else if (pixelClock > 165000)
505 		args.v1.ucLaneNum = 8;
506 	else
507 		args.v1.ucLaneNum = 4;
508 
509 	if (info.dceMajor >= 5) {
510 		if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
511 			|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
512 				if (dpClock == 270000) {
513 					args.v1.ucConfig
514 						|= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
515 				} else if (dpClock == 540000) {
516 					args.v1.ucConfig
517 						|= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
518 				}
519 		}
520 		args.v4.acConfig.ucDigSel = dig->dig_encoder;
521 		switch (bpc) {
522 			case 0:
523 				args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
524 				break;
525 			case 6:
526 				args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
527 				break;
528 			case 8:
529 			default:
530 				args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
531 				break;
532 			case 10:
533 				args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
534 				break;
535 			case 12:
536 				args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
537 				break;
538 			case 16:
539 				args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
540 				break;
541 		}
542 
543 		//if (hpdID == RADEON_HPD_NONE)
544 		if (1)
545 			args.v4.ucHPD_ID = 0;
546 		else
547 			args.v4.ucHPD_ID = hpd_id + 1;
548 
549 	} else if (info.dceMajor >= 4) {
550 		if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
551 			&& dp_clock == 270000) {
552 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
553 		}
554 
555 		args.v3.acConfig.ucDigSel = dig->dig_encoder;
556 		switch (bpc) {
557 			case 0:
558 				args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
559 				break;
560 			case 6:
561 				args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
562 				break;
563 			case 8:
564 			default:
565 				args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
566 				break;
567 			case 10:
568 				args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
569 				break;
570 			case 12:
571 				args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
572 				break;
573 			case 16:
574 				args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
575 				break;
576 		}
577 
578 	} else {
579 		if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
580 			&& dp_clock == 270000) {
581 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
582 		}
583 	#endif
584 		switch (encoderID) {
585 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
586 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
587 				break;
588 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
589 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
590 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
591 				break;
592 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
593 				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
594 				break;
595 		}
596 	#if 0
597 		if (dig->linkb)
598 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
599 		else
600 			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
601 	}
602 	#endif
603 
604 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
605 }
606 
607 
608 union external_encoder_control {
609 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
610 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
611 };
612 
613 
614 status_t
615 encoder_external_setup(uint8 id, uint32 pixelClock, int command)
616 {
617 	TRACE("%s\n", __func__);
618 
619 	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
620 	union external_encoder_control args;
621 	memset(&args, 0, sizeof(args));
622 
623 	uint32 connectorIndex = gDisplay[id]->connectorIndex;
624 	int connectorObjectID
625 		= (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
626 			>> OBJECT_ID_SHIFT;
627 
628 	uint8 tableMajor;
629 	uint8 tableMinor;
630 
631 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
632 		!= B_OK) {
633 		ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__);
634 		return B_ERROR;
635 	}
636 
637 	switch (tableMajor) {
638 		case 1:
639 			// no options needed on table 1.x
640 			break;
641 		case 2:
642 			switch (tableMinor) {
643 				case 1:
644 				case 2:
645 					args.v1.sDigEncoder.ucAction = command;
646 					args.v1.sDigEncoder.usPixelClock
647 						= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
648 					args.v1.sDigEncoder.ucEncoderMode
649 						= display_get_encoder_mode(connectorIndex);
650 					#if 0
651 					if (0) { // ENCODER_MODE_IS_DP(v1.sDigEncoder.ucEncoderMode)
652 						if (dp_clock == 270000) {
653 							args.v1.sDigEncoder.ucConfig
654 								|= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
655 						}
656 						args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
657 					} else if (pixelClock > 165000) {
658 					#endif
659 					if (pixelClock > 165000) {
660 						args.v1.sDigEncoder.ucLaneNum = 8;
661 					} else {
662 						args.v1.sDigEncoder.ucLaneNum = 4;
663 					}
664 					break;
665 				case 3:
666 				{
667 					args.v3.sExtEncoder.ucAction = command;
668 					if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) {
669 						args.v3.sExtEncoder.usConnectorId
670 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
671 					} else {
672 						args.v3.sExtEncoder.usPixelClock
673 							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
674 					}
675 
676 					args.v3.sExtEncoder.ucEncoderMode
677 						= display_get_encoder_mode(connectorIndex);
678 
679 					#if 0
680 					if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
681 						if (dp_clock == 270000) {
682 							args.v3.sExtEncoder.ucConfig
683 								|=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
684 						} else if (dp_clock == 540000) {
685 							args.v3.sExtEncoder.ucConfig
686 								|=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
687 						}
688 						args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
689 					} else if (pixelClock > 165000) {
690 					#endif
691 					if (pixelClock > 165000) {
692 						args.v3.sExtEncoder.ucLaneNum = 8;
693 					} else {
694 						args.v3.sExtEncoder.ucLaneNum = 4;
695 					}
696 
697 					uint16 encoderFlags
698 						= gConnector[connectorIndex]->encoder.flags;
699 					switch ((encoderFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) {
700 						case GRAPH_OBJECT_ENUM_ID1:
701 							TRACE("%s: external encoder 1\n", __func__);
702 							args.v3.sExtEncoder.ucConfig
703 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
704 							break;
705 						case GRAPH_OBJECT_ENUM_ID2:
706 							TRACE("%s: external encoder 2\n", __func__);
707 							args.v3.sExtEncoder.ucConfig
708 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
709 							break;
710 						case GRAPH_OBJECT_ENUM_ID3:
711 							TRACE("%s: external encoder 3\n", __func__);
712 							args.v3.sExtEncoder.ucConfig
713 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
714 							break;
715 					}
716 
717 					// TODO: don't set statically
718 					uint32 bitsPerColor = 8;
719 					switch (bitsPerColor) {
720 						case 0:
721 							args.v3.sExtEncoder.ucBitPerColor
722 								= PANEL_BPC_UNDEFINE;
723 							break;
724 						case 6:
725 							args.v3.sExtEncoder.ucBitPerColor
726 								= PANEL_6BIT_PER_COLOR;
727 							break;
728 						case 8:
729 						default:
730 							args.v3.sExtEncoder.ucBitPerColor
731 								= PANEL_8BIT_PER_COLOR;
732 							break;
733 						case 10:
734 							args.v3.sExtEncoder.ucBitPerColor
735 								= PANEL_10BIT_PER_COLOR;
736 							break;
737 						case 12:
738 							args.v3.sExtEncoder.ucBitPerColor
739 								= PANEL_12BIT_PER_COLOR;
740 							break;
741 						case 16:
742 							args.v3.sExtEncoder.ucBitPerColor
743 								= PANEL_16BIT_PER_COLOR;
744 							break;
745 					}
746 					break;
747 				}
748 				default:
749 					ERROR("%s: Unknown table minor version: "
750 						"%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
751 						tableMajor, tableMinor);
752 					return B_ERROR;
753 			}
754 			break;
755 		default:
756 			ERROR("%s: Unknown table major version: "
757 				"%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
758 				tableMajor, tableMinor);
759 			return B_ERROR;
760 	}
761 
762 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
763 }
764 
765 
766 status_t
767 encoder_analog_setup(uint8 id, uint32 pixelClock, int command)
768 {
769 	TRACE("%s\n", __func__);
770 
771 	uint32 connectorIndex = gDisplay[id]->connectorIndex;
772 
773 	int index = 0;
774 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
775 	memset(&args, 0, sizeof(args));
776 
777 	switch (gConnector[connectorIndex]->encoder.objectID) {
778 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
779 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
780 			index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
781 			break;
782 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
783 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
784 			index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
785 			break;
786 	}
787 
788 	args.ucAction = command;
789 	args.ucDacStandard = ATOM_DAC1_PS2;
790 		// TODO: or ATOM_DAC1_CV if ATOM_DEVICE_CV_SUPPORT
791 		// TODO: or ATOM_DAC1_PAL or ATOM_DAC1_NTSC if else
792 
793 	args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
794 
795 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
796 }
797 
798 
799 bool
800 encoder_analog_load_detect(uint8 connectorIndex)
801 {
802 	uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags;
803 	uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
804 
805 	if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0
806 		&& (encoderFlags & ATOM_DEVICE_CV_SUPPORT) == 0
807 		&& (encoderFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) {
808 		ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n",
809 			__func__, connectorIndex);
810 		return false;
811 	}
812 
813 	// *** tell the card we want to do a DAC detection
814 
815 	DAC_LOAD_DETECTION_PS_ALLOCATION args;
816 	int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
817 	uint8 tableMajor;
818 	uint8 tableMinor;
819 
820 	memset(&args, 0, sizeof(args));
821 
822 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
823 		!= B_OK) {
824 		ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n",
825 			__func__);
826 		return false;
827 	}
828 
829 	args.sDacload.ucMisc = 0;
830 
831 	if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1
832 		|| encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) {
833 		args.sDacload.ucDacType = ATOM_DAC_A;
834 	} else {
835 		args.sDacload.ucDacType = ATOM_DAC_B;
836 	}
837 
838 	if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
839 		args.sDacload.usDeviceID
840 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT);
841 		atom_execute_table(gAtomContext, index, (uint32*)&args);
842 
843 		uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH);
844 
845 		if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
846 			return true;
847 
848 	} else if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
849 		args.sDacload.usDeviceID
850 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT);
851 		atom_execute_table(gAtomContext, index, (uint32*)&args);
852 
853 		uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH);
854 
855 		if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
856 			return true;
857 
858 	} else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
859 		args.sDacload.usDeviceID
860 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT);
861 		if (tableMinor >= 3)
862 			args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
863 		atom_execute_table(gAtomContext, index, (uint32*)&args);
864 
865 		uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH);
866 
867 		if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
868 			return true;
869 
870 	} else if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
871 		args.sDacload.usDeviceID
872 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT);
873 		if (tableMinor >= 3)
874 			args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
875 		atom_execute_table(gAtomContext, index, (uint32*)&args);
876 
877 		uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH);
878 
879 		if ((biosScratch0
880 			& (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) {
881 			return true; /* Composite connected */
882 		} else if ((biosScratch0
883 			& (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) {
884 			return true; /* S-Video connected */
885 		}
886 
887 	}
888 	return false;
889 }
890 
891 
892 void
893 encoder_crtc_scratch(uint8 crtcID)
894 {
895 	TRACE("%s\n", __func__);
896 
897 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
898 	uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags;
899 
900 	// TODO: r500
901 	uint32 biosScratch3 = Read32(OUT, R600_BIOS_3_SCRATCH);
902 
903 	if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
904 		biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE;
905 		biosScratch3 |= (crtcID << 18);
906 	}
907 	if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
908 		biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE;
909 		biosScratch3 |= (crtcID << 24);
910 	}
911 	if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
912 		biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
913 		biosScratch3 |= (crtcID << 16);
914 	}
915 	if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
916 		biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
917 		biosScratch3 |= (crtcID << 20);
918 	}
919 	if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
920 		biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
921 		biosScratch3 |= (crtcID << 17);
922 	}
923 	if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
924 		biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
925 		biosScratch3 |= (crtcID << 19);
926 	}
927 	if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
928 		biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
929 		biosScratch3 |= (crtcID << 23);
930 	}
931 	if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
932 		biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
933 		biosScratch3 |= (crtcID << 25);
934 	}
935 
936 	// TODO: r500
937 	Write32(OUT, R600_BIOS_3_SCRATCH, biosScratch3);
938 }
939 
940 
941 void
942 encoder_dpms_scratch(uint8 crtcID, bool power)
943 {
944 	TRACE("%s: power: %s\n", __func__, power ? "true" : "false");
945 
946 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
947 	uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags;
948 
949 	// TODO: r500
950 	uint32 biosScratch2 = Read32(OUT, R600_BIOS_2_SCRATCH);
951 
952 	if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
953 		if (power == true)
954 			biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE;
955 		else
956 			biosScratch2 |= ATOM_S2_TV1_DPMS_STATE;
957 	}
958 	if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
959 		if (power == true)
960 			biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE;
961 		else
962 			biosScratch2 |= ATOM_S2_CV_DPMS_STATE;
963 	}
964 	if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
965 		if (power == true)
966 			biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE;
967 		else
968 			biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE;
969 	}
970 	if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
971 		if (power == true)
972 			biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE;
973 		else
974 			biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE;
975 	}
976 	if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
977 		if (power == true)
978 			biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE;
979 		else
980 			biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE;
981 	}
982 	if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
983 		if (power == true)
984 			biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE;
985 		else
986 			biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE;
987 	}
988 	if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
989 		if (power == true)
990 			biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE;
991 		else
992 			biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE;
993 	}
994 	if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
995 		if (power == true)
996 			biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE;
997 		else
998 			biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE;
999 	}
1000 	if ((encoderFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) {
1001 		if (power == true)
1002 			biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE;
1003 		else
1004 			biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE;
1005 	}
1006 	if ((encoderFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) {
1007 		if (power == true)
1008 			biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE;
1009 		else
1010 			biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE;
1011 	}
1012 	Write32(OUT, R600_BIOS_2_SCRATCH, biosScratch2);
1013 }
1014 
1015 
1016 void
1017 encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode)
1018 {
1019 	int index = 0;
1020 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1021 
1022 	memset(&args, 0, sizeof(args));
1023 
1024 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1025 	uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags;
1026 
1027 	switch (encoderID) {
1028 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1029 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1030 			index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1031 			break;
1032 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1033 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1034 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1035 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1036 			ERROR("%s: TODO DIG DPMS set\n", __func__);
1037 			return;
1038 		case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1039 		case ENCODER_OBJECT_ID_INTERNAL_DDI:
1040 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1041 			break;
1042 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1043 			// TODO: encoder dpms set newer cards
1044 			// If DCE5, dvo true
1045 			// If DCE3, dig true
1046 			// else...
1047 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1048 			break;
1049 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1050 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1051 			break;
1052 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1053 			if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
1054 				index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1055 			else
1056 				index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1057 			break;
1058 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1059 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1060 			// TODO: encoder dpms dce5 dac
1061 			// else...
1062 			/*
1063 			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
1064 				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1065 			else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
1066 				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1067 			else
1068 			*/
1069 			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1070 			break;
1071 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1072 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1073 			// TODO: tv or CV encoder on DAC2
1074 			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1075 			break;
1076 	}
1077 
1078 	switch (mode) {
1079 		case B_DPMS_ON:
1080 			args.ucAction = ATOM_ENABLE;
1081 			atom_execute_table(gAtomContext, index, (uint32*)&args);
1082 			if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1083 				args.ucAction = ATOM_LCD_BLON;
1084 				atom_execute_table(gAtomContext, index, (uint32*)&args);
1085 			}
1086 			encoder_dpms_scratch(crtcID, true);
1087 			break;
1088 		case B_DPMS_STAND_BY:
1089 		case B_DPMS_SUSPEND:
1090 		case B_DPMS_OFF:
1091 			args.ucAction = ATOM_DISABLE;
1092 			atom_execute_table(gAtomContext, index, (uint32*)&args);
1093 			if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1094 				args.ucAction = ATOM_LCD_BLOFF;
1095 				atom_execute_table(gAtomContext, index, (uint32*)&args);
1096 			}
1097 			encoder_dpms_scratch(crtcID, false);
1098 			break;
1099 	}
1100 }
1101 
1102 
1103 void
1104 encoder_output_lock(bool lock)
1105 {
1106 	TRACE("%s: %s\n", __func__, lock ? "true" : "false");
1107 	uint32 biosScratch6 = Read32(OUT, R600_BIOS_6_SCRATCH);
1108 
1109 	if (lock) {
1110 		biosScratch6 |= ATOM_S6_CRITICAL_STATE;
1111 		biosScratch6 &= ~ATOM_S6_ACC_MODE;
1112 	} else {
1113 		biosScratch6 &= ~ATOM_S6_CRITICAL_STATE;
1114 		biosScratch6 |= ATOM_S6_ACC_MODE;
1115 	}
1116 
1117 	Write32(OUT, R600_BIOS_6_SCRATCH, biosScratch6);
1118 }
1119 
1120 
1121 static const char *encoder_name_matrix[36] = {
1122 	"NONE",
1123 	"Internal Radeon LVDS",
1124 	"Internal Radeon TMDS1",
1125 	"Internal Radeon TMDS2",
1126 	"Internal Radeon DAC1",
1127 	"Internal Radeon DAC2 (TV)",
1128 	"Internal Radeon SDVOA",
1129 	"Internal Radeon SDVOB",
1130 	"External 3rd party SI170B",
1131 	"External 3rd party CH7303",
1132 	"External 3rd party CH7301",
1133 	"Internal Radeon DVO1",
1134 	"External 3rd party SDVOA",
1135 	"External 3rd party SDVOB",
1136 	"External 3rd party TITFP513",
1137 	"Internal LVTM1",
1138 	"External 3rd party VT1623",
1139 	"External HDMI SI1930",
1140 	"Internal HDMI",
1141 	"Internal Kaleidoscope TMDS1",
1142 	"Internal Kaleidoscope DVO1",
1143 	"Internal Kaleidoscope DAC1",
1144 	"Internal Kaleidoscope DAC2",
1145 	"External Kaleidoscope SI178",
1146 	"MVPU FPGA",
1147 	"Internal Kaleidoscope DDI",
1148 	"External Kaleidoscope VT1625",
1149 	"External Kaleidoscope HDMI SI1932",
1150 	"External Kaleidoscope DP AN9801",
1151 	"External Kaleidoscope DP DP501",
1152 	"Internal Kaleidoscope UNIPHY",
1153 	"Internal Kaleidoscope LVTMA",
1154 	"Internal Kaleidoscope UNIPHY1",
1155 	"Internal Kaleidoscope UNIPHY2",
1156 	"External Travis Bridge",
1157 	"External Nutmeg Bridge"
1158 };
1159 
1160 
1161 const char*
1162 encoder_name_lookup(uint32 encoderID) {
1163 	if (encoderID <= sizeof(encoder_name_matrix))
1164 		return encoder_name_matrix[encoderID];
1165 	else
1166 		return "Unknown";
1167 }
1168 
1169 
1170 uint32
1171 encoder_object_lookup(uint32 encoderFlags, uint8 dacID)
1172 {
1173 	// used on older cards to take a guess at the encoder
1174 	// object
1175 
1176 	radeon_shared_info &info = *gInfo->shared_info;
1177 
1178 	uint32 ret = 0;
1179 
1180 	switch (encoderFlags) {
1181 		case ATOM_DEVICE_CRT1_SUPPORT:
1182 		case ATOM_DEVICE_TV1_SUPPORT:
1183 		case ATOM_DEVICE_TV2_SUPPORT:
1184 		case ATOM_DEVICE_CRT2_SUPPORT:
1185 		case ATOM_DEVICE_CV_SUPPORT:
1186 			switch (dacID) {
1187 				case 1:
1188 					if ((info.chipsetID == RADEON_RS400)
1189 						|| (info.chipsetID == RADEON_RS480))
1190 						ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
1191 					else if (info.chipsetID >= RADEON_RS600)
1192 						ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
1193 					else
1194 						ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
1195 					break;
1196 				case 2:
1197 					if (info.chipsetID >= RADEON_RS600)
1198 						ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
1199 					else {
1200 						ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
1201 					}
1202 					break;
1203 				case 3: // external dac
1204 					if (info.chipsetID >= RADEON_RS600)
1205 						ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
1206 					else
1207 						ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
1208 					break;
1209 			}
1210 			break;
1211 		case ATOM_DEVICE_LCD1_SUPPORT:
1212 			if (info.chipsetID >= RADEON_RS600)
1213 				ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
1214 			else
1215 				ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
1216 			break;
1217 		case ATOM_DEVICE_DFP1_SUPPORT:
1218 			if ((info.chipsetID == RADEON_RS400)
1219 				|| (info.chipsetID == RADEON_RS480))
1220 				ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
1221 			else if (info.chipsetID >= RADEON_RS600)
1222 				ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
1223 			else
1224 				ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
1225 			break;
1226 		case ATOM_DEVICE_LCD2_SUPPORT:
1227 		case ATOM_DEVICE_DFP2_SUPPORT:
1228 			if ((info.chipsetID == RADEON_RS600)
1229 				|| (info.chipsetID == RADEON_RS690)
1230 				|| (info.chipsetID == RADEON_RS740))
1231 				ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
1232 			else if (info.chipsetID >= RADEON_RS600)
1233 				ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
1234 			else
1235 				ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
1236 			break;
1237 		case ATOM_DEVICE_DFP3_SUPPORT:
1238 			ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
1239 			break;
1240 	}
1241 
1242 	return ret;
1243 }
1244 
1245 
1246 uint32
1247 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags)
1248 {
1249 	switch(encoderID) {
1250 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1251 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1252 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1253 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1254 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
1255 				return VIDEO_ENCODER_LVDS;
1256 			else
1257 				return VIDEO_ENCODER_TMDS;
1258 			break;
1259 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1260 			return VIDEO_ENCODER_DAC;
1261 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1262 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1263 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1264 			return VIDEO_ENCODER_TVDAC;
1265 		case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1266 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1267 		case ENCODER_OBJECT_ID_INTERNAL_DDI:
1268 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1269 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1270 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1271 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1272 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
1273 				return VIDEO_ENCODER_LVDS;
1274 			else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
1275 				return VIDEO_ENCODER_DAC;
1276 			else
1277 				return VIDEO_ENCODER_TMDS;
1278 			break;
1279 		case ENCODER_OBJECT_ID_SI170B:
1280 		case ENCODER_OBJECT_ID_CH7303:
1281 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
1282 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
1283 		case ENCODER_OBJECT_ID_TITFP513:
1284 		case ENCODER_OBJECT_ID_VT1623:
1285 		case ENCODER_OBJECT_ID_HDMI_SI1930:
1286 		case ENCODER_OBJECT_ID_TRAVIS:
1287 		case ENCODER_OBJECT_ID_NUTMEG:
1288 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
1289 				return VIDEO_ENCODER_LVDS;
1290 			else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
1291 				return VIDEO_ENCODER_DAC;
1292 			else
1293 				return VIDEO_ENCODER_TMDS;
1294 			break;
1295 	}
1296 
1297 	return VIDEO_ENCODER_NONE;
1298 }
1299 
1300 
1301 bool
1302 encoder_is_external(uint32 encoderID)
1303 {
1304 	switch (encoderID) {
1305 		case ENCODER_OBJECT_ID_SI170B:
1306 		case ENCODER_OBJECT_ID_CH7303:
1307 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
1308 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
1309 		case ENCODER_OBJECT_ID_TITFP513:
1310 		case ENCODER_OBJECT_ID_VT1623:
1311 		case ENCODER_OBJECT_ID_HDMI_SI1930:
1312 		case ENCODER_OBJECT_ID_TRAVIS:
1313 		case ENCODER_OBJECT_ID_NUTMEG:
1314 			return true;
1315 	}
1316 
1317 	return false;
1318 }
1319 
1320 
1321 bool
1322 encoder_is_dp_bridge(uint32 encoderID) {
1323 	switch (encoderID) {
1324 		case ENCODER_OBJECT_ID_TRAVIS:
1325 		case ENCODER_OBJECT_ID_NUTMEG:
1326 			return true;
1327 	}
1328 	return false;
1329 }
1330 
1331 
1332 uint32
1333 encoder_get_dp_link_clock(uint32 connectorIndex) {
1334 	uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1335 
1336 	if (encoderID == ENCODER_OBJECT_ID_NUTMEG)
1337 		return 270000;
1338 
1339 	// TODO: calculate DisplayPort max pixel clock based on bpp and DP channels
1340 	return 162000;
1341 }
1342