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