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