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