BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / accelerants / radeon_hd / encoder.cpp
blob72a123ebb5243862fe29a3a85b5b9d9a12c44fee
1 /*
2 * Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Alexander von Gluck, kallisti5@unixzen.com
7 */
10 #include "encoder.h"
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <math.h>
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"
26 #define TRACE_ENCODER
27 #ifdef TRACE_ENCODER
28 extern "C" void _sPrintf(const char* format, ...);
29 # define TRACE(x...) _sPrintf("radeon_hd: " x)
30 #else
31 # define TRACE(x...) ;
32 #endif
34 #define ERROR(x...) _sPrintf("radeon_hd: " x)
37 void
38 encoder_init()
40 TRACE("%s: called\n", __func__);
41 radeon_shared_info &info = *gInfo->shared_info;
43 for (uint32 id = 0; id < ATOM_MAX_SUPPORTED_DEVICE; id++) {
44 if (gConnector[id]->valid == false)
45 continue;
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;
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);
69 void
70 encoder_assign_crtc(uint8 crtcID)
72 TRACE("%s\n", __func__);
74 int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
76 // Table version
77 uint8 tableMajor;
78 uint8 tableMinor;
79 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
80 != B_OK)
81 return;
83 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
84 tableMajor, tableMinor);
86 uint16 connectorIndex = gDisplay[crtcID]->connectorIndex;
87 uint16 connectorFlags = gConnector[connectorIndex]->flags;
88 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
90 // Prepare AtomBIOS command arguments
91 union crtcSourceParam {
92 SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
93 SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
95 union crtcSourceParam args;
96 memset(&args, 0, sizeof(args));
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 ((connectorFlags
125 & ATOM_DEVICE_TV_SUPPORT) != 0) {
126 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
127 } else if ((connectorFlags
128 & ATOM_DEVICE_CV_SUPPORT) != 0) {
129 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
130 } else
131 args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
132 break;
133 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
134 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
135 if ((connectorFlags
136 & ATOM_DEVICE_TV_SUPPORT) != 0) {
137 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
138 } else if ((connectorFlags
139 & ATOM_DEVICE_CV_SUPPORT) != 0) {
140 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
141 } else
142 args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
143 break;
145 break;
146 case 2:
147 args.v2.ucCRTC = crtcID;
148 args.v2.ucEncodeMode
149 = display_get_encoder_mode(connectorIndex);
150 switch (encoderID) {
151 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
152 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
153 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
154 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
155 switch (encoder_pick_dig(connectorIndex)) {
156 case 0:
157 args.v2.ucEncoderID
158 = ASIC_INT_DIG1_ENCODER_ID;
159 break;
160 case 1:
161 args.v2.ucEncoderID
162 = ASIC_INT_DIG2_ENCODER_ID;
163 break;
164 case 2:
165 args.v2.ucEncoderID
166 = ASIC_INT_DIG3_ENCODER_ID;
167 break;
168 case 3:
169 args.v2.ucEncoderID
170 = ASIC_INT_DIG4_ENCODER_ID;
171 break;
172 case 4:
173 args.v2.ucEncoderID
174 = ASIC_INT_DIG5_ENCODER_ID;
175 break;
176 case 5:
177 args.v2.ucEncoderID
178 = ASIC_INT_DIG6_ENCODER_ID;
179 break;
181 break;
182 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
183 args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
184 break;
185 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
186 if ((connectorFlags
187 & ATOM_DEVICE_TV_SUPPORT) != 0) {
188 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
189 } else if ((connectorFlags
190 & ATOM_DEVICE_CV_SUPPORT) != 0) {
191 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
192 } else
193 args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
194 break;
195 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
196 if ((connectorFlags
197 & ATOM_DEVICE_TV_SUPPORT) != 0) {
198 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
199 } else if ((connectorFlags
200 & ATOM_DEVICE_CV_SUPPORT) != 0) {
201 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
202 } else
203 args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
204 break;
206 break;
208 break;
209 default:
210 ERROR("%s: Unknown table version: %" B_PRIu8 ".%" B_PRIu8 "\n",
211 __func__, tableMajor, tableMinor);
212 return;
215 atom_execute_table(gAtomContext, index, (uint32*)&args);
217 // update crtc encoder scratch register @ scratch 3
218 encoder_crtc_scratch(crtcID);
222 uint32
223 encoder_pick_dig(uint32 connectorIndex)
225 TRACE("%s\n", __func__);
226 radeon_shared_info &info = *gInfo->shared_info;
227 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
229 // obtain assigned CRT
230 uint32 crtcID;
231 for (crtcID = 0; crtcID < MAX_DISPLAY; crtcID++) {
232 if (gDisplay[crtcID]->attached != true)
233 continue;
234 if (gDisplay[crtcID]->connectorIndex == connectorIndex)
235 break;
238 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
239 == GRAPH_OBJECT_ENUM_ID2 ? true : false;
241 uint32 dceVersion = (info.dceMajor * 100) + info.dceMinor;
243 if (dceVersion >= 400) {
244 // APU
245 switch (info.chipsetID) {
246 case RADEON_PALM:
247 return linkB ? 1 : 0;
248 case RADEON_SUMO:
249 case RADEON_SUMO2:
250 return crtcID;
253 switch (encoderID) {
254 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
255 return linkB ? 1 : 0;
256 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
257 return linkB ? 3 : 2;
258 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
259 return linkB ? 5 : 4;
263 if (dceVersion >= 302)
264 return crtcID;
266 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA)
267 return 1;
269 return 0;
273 void
274 encoder_apply_quirks(uint8 crtcID)
276 TRACE("%s\n", __func__);
277 radeon_shared_info &info = *gInfo->shared_info;
278 register_info* regs = gDisplay[crtcID]->regs;
279 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
280 uint16 connectorFlags = gConnector[connectorIndex]->flags;
282 // Setting the scaler clears this on some chips...
283 if (info.dceMajor >= 3
284 && (connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0) {
285 // TODO: assume non interleave mode for now
286 // en: EVERGREEN_INTERLEAVE_EN : AVIVO_D1MODE_INTERLEAVE_EN
287 Write32(OUT, regs->modeDataFormat, 0);
292 void
293 encoder_mode_set(uint8 crtcID)
295 TRACE("%s\n", __func__);
296 radeon_shared_info &info = *gInfo->shared_info;
297 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
298 uint16 connectorFlags = gConnector[connectorIndex]->flags;
299 pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
301 // TODO: Should this be the adjusted pll or the original?
302 uint32 pixelClock = pll->pixelClock;
304 switch (gConnector[connectorIndex]->encoder.objectID) {
305 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
306 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
307 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
308 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
309 encoder_analog_setup(connectorIndex, pixelClock, ATOM_ENABLE);
310 if (info.dceMajor < 5) {
311 // TV encoder was dropped in DCE 5
312 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0
313 || (connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
314 encoder_tv_setup(connectorIndex, pixelClock, ATOM_ENABLE);
315 } else {
316 encoder_tv_setup(connectorIndex, pixelClock, ATOM_DISABLE);
319 break;
320 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
321 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
322 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
323 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
324 encoder_digital_setup(connectorIndex, pixelClock,
325 PANEL_ENCODER_ACTION_ENABLE);
326 break;
327 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
328 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
329 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
330 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
331 if ((info.chipsetFlags & CHIP_APU) != 0
332 || info.dceMajor >= 5) {
333 // Setup DIG encoder
334 encoder_dig_setup(connectorIndex, pixelClock,
335 ATOM_ENCODER_CMD_SETUP);
336 encoder_dig_setup(connectorIndex, pixelClock,
337 ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
338 } else if (info.dceMajor >= 4) {
339 // Disable DIG transmitter
340 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
341 ATOM_TRANSMITTER_ACTION_DISABLE);
342 // Setup DIG encoder
343 encoder_dig_setup(connectorIndex, pixelClock,
344 ATOM_ENCODER_CMD_SETUP);
345 // Enable DIG transmitter
346 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
347 ATOM_TRANSMITTER_ACTION_ENABLE);
348 } else {
349 // Disable DIG transmitter
350 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
351 ATOM_TRANSMITTER_ACTION_DISABLE);
352 // Disable DIG encoder
353 encoder_dig_setup(connectorIndex, pixelClock, ATOM_DISABLE);
354 // Enable the DIG encoder
355 encoder_dig_setup(connectorIndex, pixelClock, ATOM_ENABLE);
357 // Setup and enable DIG transmitter
358 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
359 ATOM_TRANSMITTER_ACTION_SETUP);
360 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
361 ATOM_TRANSMITTER_ACTION_ENABLE);
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;
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);
381 encoder_apply_quirks(crtcID);
385 status_t
386 encoder_tv_setup(uint32 connectorIndex, uint32 pixelClock, int command)
388 uint16 connectorFlags = gConnector[connectorIndex]->flags;
390 TV_ENCODER_CONTROL_PS_ALLOCATION args;
391 memset(&args, 0, sizeof(args));
393 int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
395 args.sTVEncoder.ucAction = command;
397 if ((connectorFlags & 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;
404 args.sTVEncoder.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
406 return atom_execute_table(gAtomContext, index, (uint32*)&args);
410 status_t
411 encoder_digital_setup(uint32 connectorIndex, uint32 pixelClock, int command)
413 TRACE("%s\n", __func__);
415 int index = 0;
416 uint16 connectorFlags = gConnector[connectorIndex]->flags;
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 ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
428 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
429 else
430 index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
431 break;
434 // Table verson
435 uint8 tableMajor;
436 uint8 tableMinor;
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;
444 uint32 lvdsFlags = gConnector[connectorIndex]->lvdsFlags;
446 bool isHdmi = false;
447 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_HDMIA
448 || gConnector[connectorIndex]->type == VIDEO_CONNECTOR_HDMIB) {
449 isHdmi = true;
452 // Prepare AtomBIOS command arguments
453 union lvdsEncoderControl {
454 LVDS_ENCODER_CONTROL_PS_ALLOCATION v1;
455 LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
457 union lvdsEncoderControl args;
458 memset(&args, 0, sizeof(args));
460 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
461 tableMajor, tableMinor);
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);
474 if ((connectorFlags & 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;
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;
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 ((connectorFlags & 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;
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;
520 if (((lvdsFlags >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT)
521 & 0x3) == 2) {
522 args.v2.ucTemporal
523 |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
526 } else {
527 //if (dig->linkb)
528 // args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
529 if (pixelClock > 165000)
530 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
532 break;
533 default:
534 ERROR("%s: Unknown minor table version: %"
535 B_PRIu8 ".%" B_PRIu8 "\n", __func__,
536 tableMajor, tableMinor);
537 return B_ERROR;
539 break;
540 default:
541 ERROR("%s: Unknown major table version: %" B_PRIu8 ".%" B_PRIu8 "\n",
542 __func__, tableMajor, tableMinor);
543 return B_ERROR;
545 return atom_execute_table(gAtomContext, index, (uint32*)&args);
549 status_t
550 encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command)
552 radeon_shared_info &info = *gInfo->shared_info;
553 connector_info* connector = gConnector[connectorIndex];
555 int index = 0;
556 if (info.dceMajor >= 4)
557 index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
558 else {
559 if (encoder_pick_dig(connectorIndex))
560 index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
561 else
562 index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
565 // Table verson
566 uint8 tableMajor;
567 uint8 tableMinor;
569 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
570 != B_OK) {
571 ERROR("%s: cannot parse command table\n", __func__);
572 return B_ERROR;
575 // Prepare AtomBIOS command arguments
576 union digEncoderControl {
577 DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
578 DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
579 DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
580 DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
582 union digEncoderControl args;
583 memset(&args, 0, sizeof(args));
585 bool isDPBridge = connector->encoderExternal.isDPBridge;
586 bool linkB = connector->encoder.linkEnumeration
587 == GRAPH_OBJECT_ENUM_ID2 ? true : false;
588 uint32 digEncoderID = encoder_pick_dig(connectorIndex);
590 uint32 panelMode = 0;
591 // determine DP panel mode if doing panel mode setup
592 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) {
593 if (info.dceMajor >= 4 && isDPBridge) {
594 if (connector->encoderExternal.objectID == ENCODER_OBJECT_ID_NUTMEG)
595 panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
596 else if (connector->encoderExternal.objectID
597 == ENCODER_OBJECT_ID_TRAVIS) {
598 dp_info* dp = &gConnector[connectorIndex]->dpInfo;
599 uint8 id[6];
600 int bit;
601 for (bit = 0; bit < 6; bit++)
602 id[bit] = dpcd_reg_read(dp->auxPin, 0x503 + bit);
603 if (id[0] == 0x73 && id[1] == 0x69 && id[2] == 0x76
604 && id[3] == 0x61 && id[4] == 0x72 && id[5] == 0x54) {
605 panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
606 } else {
607 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
609 } else {
610 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
612 } else
613 panelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
616 #if 0
617 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
618 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) {
619 uint8 temp = dpcd_read_reg(hwPin, DP_EDP_CONFIGURATION_CAP);
620 if ((temp & 1) != 0)
621 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
623 #endif
625 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
626 tableMajor, tableMinor);
628 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
629 uint32 dpClock = 0;
630 if (dpInfo->valid == true)
631 dpClock = dpInfo->linkRate;
633 bool dualLink = false;
634 if (connector->type == VIDEO_CONNECTOR_DVID
635 && pixelClock > 165000) {
636 // TODO: Expand on this duallink code
637 dualLink = true;
640 // Careful! The mapping of ucHPD_ID differs between atombios calls
641 uint16 hpdID = connector_pick_atom_hpdid(connectorIndex);
643 switch (tableMinor) {
644 case 1:
645 args.v1.ucAction = command;
646 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
648 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
649 args.v3.ucPanelMode = panelMode;
650 else {
651 args.v1.ucEncoderMode
652 = display_get_encoder_mode(connectorIndex);
655 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
656 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
657 args.v1.ucLaneNum = dpInfo->laneCount;
658 } else if (dualLink)
659 args.v1.ucLaneNum = 8;
660 else
661 args.v1.ucLaneNum = 4;
663 if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
664 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
665 && dpClock == 270000) {
666 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
669 switch (connector->encoder.objectID) {
670 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
671 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
672 break;
673 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
674 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
675 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
676 break;
677 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
678 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
679 break;
682 if (linkB)
683 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
684 else
685 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
686 break;
687 case 2:
688 case 3:
689 args.v3.ucAction = command;
690 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
692 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
693 args.v3.ucPanelMode = panelMode;
694 else {
695 args.v3.ucEncoderMode
696 = display_get_encoder_mode(connectorIndex);
699 if (args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP
700 || args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
701 args.v3.ucLaneNum = dpInfo->laneCount;
702 } else if (dualLink)
703 args.v3.ucLaneNum = 8;
704 else
705 args.v3.ucLaneNum = 4;
707 if ((args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP
708 || args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
709 && dpClock == 270000) {
710 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
713 args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex);
715 // TODO: get BPC
716 switch (8) {
717 case 0:
718 args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
719 break;
720 case 6:
721 args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
722 break;
723 case 8:
724 default:
725 args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
726 break;
727 case 10:
728 args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
729 break;
730 case 12:
731 args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
732 break;
733 case 16:
734 args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
735 break;
737 break;
738 case 4:
739 args.v4.ucAction = command;
740 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
742 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
743 args.v4.ucPanelMode = panelMode;
744 else {
745 args.v4.ucEncoderMode
746 = display_get_encoder_mode(connectorIndex);
749 if (args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP
750 || args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
751 // Is DP?
752 args.v4.ucLaneNum = dpInfo->laneCount;
753 if (dpClock == 270000) {
754 args.v4.ucConfig
755 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
756 } else if (dpClock == 540000) {
757 args.v4.ucConfig
758 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
760 } else if (dualLink) {
761 // DualLink, double the lane numbers
762 args.v4.ucLaneNum = 8;
763 } else {
764 args.v4.ucLaneNum = 4;
766 args.v4.acConfig.ucDigSel = digEncoderID;
768 // TODO: get BPC
769 switch (8) {
770 case 0:
771 args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
772 break;
773 case 6:
774 args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
775 break;
776 case 8:
777 default:
778 args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
779 break;
780 case 10:
781 args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
782 break;
783 case 12:
784 args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
785 break;
786 case 16:
787 args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
788 break;
791 if (hpdID == 0xff)
792 args.v4.ucHPD_ID = 0;
793 else
794 args.v4.ucHPD_ID = hpdID + 1;
795 break;
796 default:
797 ERROR("%s: unknown tableMinor!\n", __func__);
800 status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);
802 #if 0
803 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP
804 && panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) {
805 dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1);
807 #endif
809 return result;
813 status_t
814 encoder_external_setup(uint32 connectorIndex, int command)
816 TRACE("%s\n", __func__);
818 encoder_info* encoder
819 = &gConnector[connectorIndex]->encoder;
820 encoder_info* extEncoder
821 = &gConnector[connectorIndex]->encoderExternal;
822 uint32 connectorFlags = gConnector[connectorIndex]->flags;
824 dp_info* dpInfo
825 = &gConnector[connectorIndex]->dpInfo;
827 if (extEncoder->valid != true) {
828 ERROR("%s: connector %" B_PRIu32 " doesn't have a valid "
829 "external encoder!", __func__, connectorIndex);
830 return B_ERROR;
833 uint8 tableMajor;
834 uint8 tableMinor;
836 int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
837 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
838 != B_OK) {
839 ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__);
840 return B_ERROR;
843 // Prepare AtomBIOS command arguments
844 union externalEncoderControl {
845 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
846 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
848 union externalEncoderControl args;
849 memset(&args, 0, sizeof(args));
851 int connectorObjectID
852 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
853 >> OBJECT_ID_SHIFT;
855 uint32 pixelClock = encoder->pll.pixelClock;
857 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
858 tableMajor, tableMinor);
859 switch (tableMajor) {
860 case 1:
861 // no options needed on table 1.x
862 break;
863 case 2:
864 switch (tableMinor) {
865 case 1:
866 case 2:
867 args.v1.sDigEncoder.ucAction = command;
868 args.v1.sDigEncoder.usPixelClock
869 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
870 args.v1.sDigEncoder.ucEncoderMode
871 = display_get_encoder_mode(connectorIndex);
873 if (connector_is_dp(connectorIndex)) {
874 if (dpInfo->linkRate == 270000) {
875 args.v1.sDigEncoder.ucConfig
876 |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
878 args.v1.sDigEncoder.ucLaneNum
879 = dpInfo->laneCount;
880 } else if (pixelClock > 165000) {
881 args.v1.sDigEncoder.ucLaneNum = 8;
882 } else {
883 args.v1.sDigEncoder.ucLaneNum = 4;
885 break;
886 case 3:
888 args.v3.sExtEncoder.ucAction = command;
889 if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) {
890 args.v3.sExtEncoder.usConnectorId
891 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
892 } else {
893 args.v3.sExtEncoder.usPixelClock
894 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
897 args.v3.sExtEncoder.ucEncoderMode
898 = display_get_encoder_mode(connectorIndex);
900 if (connector_is_dp(connectorIndex)) {
901 if (dpInfo->linkRate == 270000) {
902 args.v3.sExtEncoder.ucConfig
903 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
904 } else if (dpInfo->linkRate == 540000) {
905 args.v3.sExtEncoder.ucConfig
906 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
908 args.v1.sDigEncoder.ucLaneNum
909 = dpInfo->laneCount;
910 } else if (pixelClock > 165000) {
911 args.v3.sExtEncoder.ucLaneNum = 8;
912 } else {
913 args.v3.sExtEncoder.ucLaneNum = 4;
916 switch ((connectorFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) {
917 case GRAPH_OBJECT_ENUM_ID1:
918 TRACE("%s: external encoder 1\n", __func__);
919 args.v3.sExtEncoder.ucConfig
920 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
921 break;
922 case GRAPH_OBJECT_ENUM_ID2:
923 TRACE("%s: external encoder 2\n", __func__);
924 args.v3.sExtEncoder.ucConfig
925 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
926 break;
927 case GRAPH_OBJECT_ENUM_ID3:
928 TRACE("%s: external encoder 3\n", __func__);
929 args.v3.sExtEncoder.ucConfig
930 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
931 break;
934 // TODO: don't set statically
935 uint32 bitsPerColor = 8;
936 switch (bitsPerColor) {
937 case 0:
938 args.v3.sExtEncoder.ucBitPerColor
939 = PANEL_BPC_UNDEFINE;
940 break;
941 case 6:
942 args.v3.sExtEncoder.ucBitPerColor
943 = PANEL_6BIT_PER_COLOR;
944 break;
945 case 8:
946 default:
947 args.v3.sExtEncoder.ucBitPerColor
948 = PANEL_8BIT_PER_COLOR;
949 break;
950 case 10:
951 args.v3.sExtEncoder.ucBitPerColor
952 = PANEL_10BIT_PER_COLOR;
953 break;
954 case 12:
955 args.v3.sExtEncoder.ucBitPerColor
956 = PANEL_12BIT_PER_COLOR;
957 break;
958 case 16:
959 args.v3.sExtEncoder.ucBitPerColor
960 = PANEL_16BIT_PER_COLOR;
961 break;
963 break;
965 default:
966 ERROR("%s: Unknown table minor version: "
967 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
968 tableMajor, tableMinor);
969 return B_ERROR;
971 break;
972 default:
973 ERROR("%s: Unknown table major version: "
974 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
975 tableMajor, tableMinor);
976 return B_ERROR;
979 return atom_execute_table(gAtomContext, index, (uint32*)&args);
983 status_t
984 encoder_analog_setup(uint32 connectorIndex, uint32 pixelClock, int command)
986 TRACE("%s\n", __func__);
988 uint32 connectorFlags = gConnector[connectorIndex]->flags;
990 int index = 0;
991 DAC_ENCODER_CONTROL_PS_ALLOCATION args;
992 memset(&args, 0, sizeof(args));
994 switch (gConnector[connectorIndex]->encoder.objectID) {
995 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
996 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
997 index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
998 break;
999 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1000 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1001 index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
1002 break;
1005 args.ucAction = command;
1007 if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
1008 args.ucDacStandard = ATOM_DAC1_PS2;
1009 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1010 args.ucDacStandard = ATOM_DAC1_CV;
1011 else {
1012 TRACE("%s: TODO, hardcoded NTSC TV support\n", __func__);
1013 if (1) {
1014 // NTSC, NTSC_J, PAL 60
1015 args.ucDacStandard = ATOM_DAC1_NTSC;
1016 } else {
1017 // PAL, SCART. SECAM, PAL_CN
1018 args.ucDacStandard = ATOM_DAC1_PAL;
1022 args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1024 return atom_execute_table(gAtomContext, index, (uint32*)&args);
1028 bool
1029 encoder_analog_load_detect(uint32 connectorIndex)
1031 TRACE("%s\n", __func__);
1033 if (gConnector[connectorIndex]->encoderExternal.valid == true)
1034 return encoder_dig_load_detect(connectorIndex);
1036 return encoder_dac_load_detect(connectorIndex);
1040 bool
1041 encoder_dac_load_detect(uint32 connectorIndex)
1043 TRACE("%s\n", __func__);
1045 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1046 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
1048 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0
1049 && (connectorFlags & ATOM_DEVICE_CV_SUPPORT) == 0
1050 && (connectorFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) {
1051 ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n",
1052 __func__, connectorIndex);
1053 return false;
1056 // *** tell the card we want to do a DAC detection
1058 DAC_LOAD_DETECTION_PS_ALLOCATION args;
1059 int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1060 uint8 tableMajor;
1061 uint8 tableMinor;
1063 memset(&args, 0, sizeof(args));
1065 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
1066 != B_OK) {
1067 ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n",
1068 __func__);
1069 return false;
1072 args.sDacload.ucMisc = 0;
1074 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1
1075 || encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) {
1076 args.sDacload.ucDacType = ATOM_DAC_A;
1077 } else {
1078 args.sDacload.ucDacType = ATOM_DAC_B;
1081 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1082 args.sDacload.usDeviceID
1083 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT);
1084 atom_execute_table(gAtomContext, index, (uint32*)&args);
1086 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1088 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
1089 return true;
1091 } else if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1092 args.sDacload.usDeviceID
1093 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT);
1094 atom_execute_table(gAtomContext, index, (uint32*)&args);
1096 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1098 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
1099 return true;
1101 } else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1102 args.sDacload.usDeviceID
1103 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT);
1104 if (tableMinor >= 3)
1105 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1106 atom_execute_table(gAtomContext, index, (uint32*)&args);
1108 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1110 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
1111 return true;
1113 } else if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1114 args.sDacload.usDeviceID
1115 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT);
1116 if (tableMinor >= 3)
1117 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1118 atom_execute_table(gAtomContext, index, (uint32*)&args);
1120 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1122 if ((biosScratch0
1123 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) {
1124 return true; /* Composite connected */
1125 } else if ((biosScratch0
1126 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) {
1127 return true; /* S-Video connected */
1131 return false;
1135 bool
1136 encoder_dig_load_detect(uint32 connectorIndex)
1138 TRACE("%s\n", __func__);
1139 radeon_shared_info &info = *gInfo->shared_info;
1141 if (info.dceMajor < 4) {
1142 ERROR("%s: Strange: External DIG encoder on DCE < 4?\n", __func__);
1143 return false;
1146 encoder_external_setup(connectorIndex,
1147 EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
1149 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1151 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1153 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0)
1154 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
1155 return true;
1156 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0)
1157 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
1158 return true;
1159 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1160 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
1161 return true;
1162 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1163 if ((biosScratch0
1164 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0)
1165 return true; /* Composite connected */
1166 else if ((biosScratch0
1167 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0)
1168 return true; /* S-Video connected */
1171 return false;
1175 status_t
1176 transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
1177 uint8 laneNumber, uint8 laneSet, int command)
1179 TRACE("%s\n", __func__);
1181 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1182 int index;
1183 switch (encoderID) {
1184 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1185 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1186 break;
1187 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1188 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1189 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1190 index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1191 break;
1192 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1193 index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
1194 break;
1195 default:
1196 ERROR("%s: BUG: dig setup run on non-dig encoder!\n", __func__);
1197 return B_ERROR;
1200 if (index < 0) {
1201 ERROR("%s: GetIndexIntoMasterTable failed!\n", __func__);
1202 return B_ERROR;
1205 uint8 tableMajor;
1206 uint8 tableMinor;
1208 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
1209 != B_OK)
1210 return B_ERROR;
1212 // Prepare AtomBIOS arguments
1213 union digTransmitterControl {
1214 DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
1215 DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
1216 DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
1217 DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
1218 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
1220 union digTransmitterControl args;
1221 memset(&args, 0, sizeof(args));
1223 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
1224 tableMajor, tableMinor);
1226 int connectorObjectID
1227 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
1228 >> OBJECT_ID_SHIFT;
1229 uint32 encoderObjectID = gConnector[connectorIndex]->encoder.objectID;
1230 uint32 digEncoderID = encoder_pick_dig(connectorIndex);
1232 pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
1234 bool isDP = connector_is_dp(connectorIndex);
1235 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
1236 == GRAPH_OBJECT_ENUM_ID2 ? true : false;
1238 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
1240 uint32 dpClock = 0;
1241 int dpLaneCount = 0;
1242 if (dpInfo->valid == true) {
1243 dpClock = dpInfo->linkRate;
1244 dpLaneCount = dpInfo->laneCount;
1247 switch (tableMajor) {
1248 case 1:
1249 switch (tableMinor) {
1250 case 1:
1251 args.v1.ucAction = command;
1252 if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1253 args.v1.usInitInfo
1254 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1255 } else if (command
1256 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1257 args.v1.asMode.ucLaneSel = laneNumber;
1258 args.v1.asMode.ucLaneSet = laneSet;
1259 } else {
1260 if (isDP) {
1261 args.v1.usPixelClock
1262 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1263 } else if (pixelClock > 165000) {
1264 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1265 (pixelClock / 2) / 10);
1266 } else {
1267 args.v1.usPixelClock
1268 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1272 args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1274 if (digEncoderID > 0) {
1275 args.v1.ucConfig
1276 |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
1277 } else {
1278 args.v1.ucConfig
1279 |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1282 // TODO: IGP DIG Transmitter setup
1283 #if 0
1284 if ((rdev->flags & RADEON_IS_IGP) && (encoderObjectID
1285 == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1286 if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
1287 if (igp_lane_info & 0x1)
1288 args.v1.ucConfig
1289 |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
1290 else if (igp_lane_info & 0x2)
1291 args.v1.ucConfig
1292 |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
1293 else if (igp_lane_info & 0x4)
1294 args.v1.ucConfig
1295 |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
1296 else if (igp_lane_info & 0x8)
1297 args.v1.ucConfig
1298 |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1299 } else {
1300 if (igp_lane_info & 0x3)
1301 args.v1.ucConfig
1302 |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
1303 else if (igp_lane_info & 0xc)
1304 args.v1.ucConfig
1305 |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1308 #endif
1310 if (linkB == true)
1311 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
1312 else
1313 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
1315 if (isDP)
1316 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1317 else if ((gConnector[connectorIndex]->flags
1318 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1319 if (1) {
1320 // if coherentMode, i've only ever seen it true
1321 args.v1.ucConfig
1322 |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1324 if (pixelClock > 165000) {
1325 args.v1.ucConfig
1326 |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1329 break;
1330 case 2:
1331 args.v2.ucAction = command;
1332 if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1333 args.v2.usInitInfo
1334 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1335 } else if (command
1336 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1337 args.v2.asMode.ucLaneSel = laneNumber;
1338 args.v2.asMode.ucLaneSet = laneSet;
1339 } else {
1340 if (isDP) {
1341 args.v2.usPixelClock
1342 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1343 } else if (pixelClock > 165000) {
1344 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1345 (pixelClock / 2) / 10);
1346 } else {
1347 args.v2.usPixelClock
1348 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1351 args.v2.acConfig.ucEncoderSel = digEncoderID;
1352 if (linkB)
1353 args.v2.acConfig.ucLinkSel = 1;
1355 switch (encoderObjectID) {
1356 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1357 args.v2.acConfig.ucTransmitterSel = 0;
1358 break;
1359 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1360 args.v2.acConfig.ucTransmitterSel = 1;
1361 break;
1362 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1363 args.v2.acConfig.ucTransmitterSel = 2;
1364 break;
1367 if (isDP) {
1368 args.v2.acConfig.fCoherentMode = 1;
1369 args.v2.acConfig.fDPConnector = 1;
1370 } else if ((gConnector[connectorIndex]->flags
1371 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1372 if (1) {
1373 // if coherentMode, i've only ever seen it true
1374 args.v2.acConfig.fCoherentMode = 1;
1377 if (pixelClock > 165000)
1378 args.v2.acConfig.fDualLinkConnector = 1;
1380 break;
1381 case 3:
1382 args.v3.ucAction = command;
1383 if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1384 args.v3.usInitInfo
1385 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1386 } else if (command
1387 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1388 args.v3.asMode.ucLaneSel = laneNumber;
1389 args.v3.asMode.ucLaneSet = laneSet;
1390 } else {
1391 if (isDP) {
1392 args.v3.usPixelClock
1393 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1394 } else if (pixelClock > 165000) {
1395 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1396 (pixelClock / 2) / 10);
1397 } else {
1398 args.v3.usPixelClock
1399 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1403 if (isDP)
1404 args.v3.ucLaneNum = dpLaneCount;
1405 else if (pixelClock > 165000)
1406 args.v3.ucLaneNum = 8;
1407 else
1408 args.v3.ucLaneNum = 4;
1410 if (linkB == true)
1411 args.v3.acConfig.ucLinkSel = 1;
1412 if (digEncoderID & 1)
1413 args.v3.acConfig.ucEncoderSel = 1;
1415 // Select the PLL for the PHY
1416 // DP PHY to be clocked from external src if possible
1418 // DCE4 has external DCPLL clock for DP
1419 if (isDP && gInfo->dpExternalClock) {
1420 // use external clock source (id'ed to 2 on DCE4)
1421 args.v3.acConfig.ucRefClkSource = 2; // EXT clock
1422 } else
1423 args.v3.acConfig.ucRefClkSource = pll->id;
1425 switch (encoderObjectID) {
1426 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1427 args.v3.acConfig.ucTransmitterSel = 0;
1428 break;
1429 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1430 args.v3.acConfig.ucTransmitterSel = 1;
1431 break;
1432 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1433 args.v3.acConfig.ucTransmitterSel = 2;
1434 break;
1437 if (isDP)
1438 args.v3.acConfig.fCoherentMode = 1;
1439 else if ((gConnector[connectorIndex]->flags
1440 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1441 if (1) {
1442 // if coherentMode, i've only ever seen it true
1443 args.v3.acConfig.fCoherentMode = 1;
1445 if (pixelClock > 165000)
1446 args.v3.acConfig.fDualLinkConnector = 1;
1448 break;
1449 case 4:
1450 args.v4.ucAction = command;
1451 if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1452 args.v4.usInitInfo
1453 = B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1454 } else if (command
1455 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1456 args.v4.asMode.ucLaneSel = laneNumber;
1457 args.v4.asMode.ucLaneSet = laneSet;
1458 } else {
1459 if (isDP) {
1460 args.v4.usPixelClock
1461 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1462 } else if (pixelClock > 165000) {
1463 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1464 (pixelClock / 2) / 10);
1465 } else {
1466 args.v4.usPixelClock
1467 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1471 if (isDP)
1472 args.v4.ucLaneNum = dpLaneCount;
1473 else if (pixelClock > 165000)
1474 args.v4.ucLaneNum = 8;
1475 else
1476 args.v4.ucLaneNum = 4;
1478 if (linkB == true)
1479 args.v4.acConfig.ucLinkSel = 1;
1480 if (digEncoderID & 1)
1481 args.v4.acConfig.ucEncoderSel = 1;
1483 // Select the PLL for the PHY
1484 // DP PHY to be clocked from external src if possible
1485 // DCE5, DCPLL usually generates the DP ref clock
1486 if (isDP) {
1487 if (gInfo->dpExternalClock > 0) {
1488 args.v4.acConfig.ucRefClkSource
1489 = ENCODER_REFCLK_SRC_EXTCLK;
1490 } else {
1491 args.v4.acConfig.ucRefClkSource
1492 = ENCODER_REFCLK_SRC_DCPLL;
1494 } else
1495 args.v4.acConfig.ucRefClkSource = pll->id;
1497 switch (encoderObjectID) {
1498 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1499 args.v4.acConfig.ucTransmitterSel = 0;
1500 break;
1501 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1502 args.v4.acConfig.ucTransmitterSel = 1;
1503 break;
1504 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1505 args.v4.acConfig.ucTransmitterSel = 2;
1506 break;
1509 if (isDP)
1510 args.v4.acConfig.fCoherentMode = 1;
1511 else if ((gConnector[connectorIndex]->flags
1512 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1513 if (1) {
1514 // if coherentMode, i've only ever seen it true
1515 args.v4.acConfig.fCoherentMode = 1;
1517 if (pixelClock > 165000)
1518 args.v4.acConfig.fDualLinkConnector = 1;
1520 break;
1521 case 5:
1522 args.v5.ucAction = command;
1524 if (isDP) {
1525 args.v5.usSymClock
1526 = B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1527 } else {
1528 args.v5.usSymClock
1529 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1531 switch (encoderObjectID) {
1532 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1533 if (linkB)
1534 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1535 else
1536 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1537 break;
1538 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1539 if (linkB)
1540 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1541 else
1542 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1543 break;
1544 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1545 if (linkB)
1546 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1547 else
1548 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1549 break;
1551 if (isDP) {
1552 args.v5.ucLaneNum = dpLaneCount;
1553 } else if (pixelClock >= 165000) {
1554 args.v5.ucLaneNum = 8;
1555 } else {
1556 args.v5.ucLaneNum = 4;
1559 args.v5.ucConnObjId = connectorObjectID;
1560 args.v5.ucDigMode
1561 = display_get_encoder_mode(connectorIndex);
1563 if (isDP && gInfo->dpExternalClock) {
1564 args.v5.asConfig.ucPhyClkSrcId
1565 = ENCODER_REFCLK_SRC_EXTCLK;
1566 } else {
1567 args.v5.asConfig.ucPhyClkSrcId = pll->id;
1570 if (isDP) {
1571 args.v5.asConfig.ucCoherentMode = 1;
1572 // DP always coherent
1573 } else if ((gConnector[connectorIndex]->flags
1574 & ATOM_DEVICE_DFP_SUPPORT) != 0) {
1575 // TODO: dig coherent mode? VVV
1576 args.v5.asConfig.ucCoherentMode = 1;
1579 // RADEON_HPD_NONE? VVV
1580 args.v5.asConfig.ucHPDSel = 0;
1582 args.v5.ucDigEncoderSel = 1 << digEncoderID;
1583 args.v5.ucDPLaneSet = laneSet;
1584 break;
1585 default:
1586 ERROR("%s: unknown table version\n", __func__);
1588 break;
1589 default:
1590 ERROR("%s: unknown table version\n", __func__);
1593 return atom_execute_table(gAtomContext, index, (uint32*)&args);
1597 void
1598 encoder_crtc_scratch(uint8 crtcID)
1600 TRACE("%s\n", __func__);
1602 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1603 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1605 // TODO: r500
1606 uint32 biosScratch3 = Read32(OUT, R600_SCRATCH_REG3);
1608 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1609 biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE;
1610 biosScratch3 |= (crtcID << 18);
1612 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1613 biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE;
1614 biosScratch3 |= (crtcID << 24);
1616 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1617 biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
1618 biosScratch3 |= (crtcID << 16);
1620 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1621 biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
1622 biosScratch3 |= (crtcID << 20);
1624 if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
1625 biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
1626 biosScratch3 |= (crtcID << 17);
1628 if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
1629 biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
1630 biosScratch3 |= (crtcID << 19);
1632 if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
1633 biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
1634 biosScratch3 |= (crtcID << 23);
1636 if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
1637 biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
1638 biosScratch3 |= (crtcID << 25);
1641 // TODO: r500
1642 Write32(OUT, R600_SCRATCH_REG3, biosScratch3);
1646 void
1647 encoder_dpms_scratch(uint8 crtcID, bool power)
1649 TRACE("%s\n", __func__);
1651 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1652 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1654 // TODO: r500
1655 uint32 biosScratch2 = Read32(OUT, R600_SCRATCH_REG2);
1657 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1658 if (power == true)
1659 biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE;
1660 else
1661 biosScratch2 |= ATOM_S2_TV1_DPMS_STATE;
1663 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1664 if (power == true)
1665 biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE;
1666 else
1667 biosScratch2 |= ATOM_S2_CV_DPMS_STATE;
1669 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1670 if (power == true)
1671 biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE;
1672 else
1673 biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE;
1675 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1676 if (power == true)
1677 biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE;
1678 else
1679 biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE;
1681 if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
1682 if (power == true)
1683 biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE;
1684 else
1685 biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE;
1687 if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
1688 if (power == true)
1689 biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE;
1690 else
1691 biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE;
1693 if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
1694 if (power == true)
1695 biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE;
1696 else
1697 biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE;
1699 if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
1700 if (power == true)
1701 biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE;
1702 else
1703 biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE;
1705 if ((connectorFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) {
1706 if (power == true)
1707 biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE;
1708 else
1709 biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE;
1711 if ((connectorFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) {
1712 if (power == true)
1713 biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE;
1714 else
1715 biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE;
1717 Write32(OUT, R600_SCRATCH_REG2, biosScratch2);
1721 void
1722 encoder_dpms_set(uint8 crtcID, int mode)
1724 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false");
1726 int index = -1;
1727 radeon_shared_info &info = *gInfo->shared_info;
1729 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1730 memset(&args, 0, sizeof(args));
1732 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1733 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1734 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1736 switch (encoderID) {
1737 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1738 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1739 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1740 break;
1741 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1742 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1743 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1744 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1745 encoder_dpms_set_dig(crtcID, mode);
1746 break;
1747 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1748 case ENCODER_OBJECT_ID_INTERNAL_DDI:
1749 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1750 break;
1751 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1752 if (info.dceMajor >= 5)
1753 encoder_dpms_set_dvo(crtcID, mode);
1754 else if (info.dceMajor >= 3)
1755 encoder_dpms_set_dig(crtcID, mode);
1756 else
1757 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1758 break;
1759 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1760 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1761 break;
1762 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1763 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
1764 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1765 else
1766 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1767 break;
1768 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1769 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1770 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
1771 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1772 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1773 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1774 else
1775 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1776 break;
1777 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1778 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1779 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
1780 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1781 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1782 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1783 else
1784 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1785 break;
1786 // default, none on purpose
1789 // If we have an index, we need to execute a table.
1790 if (index >= 0) {
1791 switch (mode) {
1792 case B_DPMS_ON:
1793 args.ucAction = ATOM_ENABLE;
1794 break;
1795 case B_DPMS_STAND_BY:
1796 case B_DPMS_SUSPEND:
1797 case B_DPMS_OFF:
1798 args.ucAction = ATOM_DISABLE;
1799 break;
1802 atom_execute_table(gAtomContext, index, (uint32*)&args);
1803 if (info.dceMajor < 5) {
1804 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1805 args.ucAction = args.ucAction == ATOM_DISABLE
1806 ? ATOM_LCD_BLOFF : ATOM_LCD_BLON;
1807 atom_execute_table(gAtomContext, index, (uint32*)&args);
1809 encoder_dpms_scratch(crtcID, true);
1813 // If an external encoder exists, we should flip it on as well
1814 if (gConnector[connectorIndex]->encoderExternal.valid == true)
1815 encoder_dpms_set_external(crtcID, mode);
1819 void
1820 encoder_dpms_set_dig(uint8 crtcID, int mode)
1822 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false");
1824 radeon_shared_info &info = *gInfo->shared_info;
1825 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1826 uint32 connectorFlags = gConnector[connectorIndex]->flags;
1827 pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
1829 switch (mode) {
1830 case B_DPMS_ON:
1831 if (info.chipsetID == RADEON_RV710
1832 || info.chipsetID == RADEON_RV730
1833 || (info.chipsetFlags & CHIP_APU) != 0
1834 || info.dceMajor >= 5) {
1835 if (info.dceMajor >= 6) {
1836 /* We need to call CMD_SETUP before reenabling the encoder,
1837 otherwise we never get a picture */
1838 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1839 ATOM_ENCODER_CMD_SETUP);
1841 encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_ENABLE);
1842 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1843 ATOM_TRANSMITTER_ACTION_SETUP);
1844 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1845 ATOM_TRANSMITTER_ACTION_ENABLE);
1846 /* some early dce3.2 boards have a bug in their transmitter
1847 control table */
1848 if (info.chipsetID != RADEON_RV710
1849 && info.chipsetID != RADEON_RV730)
1850 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1851 ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
1852 } else {
1853 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1854 ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
1856 if (connector_is_dp(connectorIndex)) {
1857 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) {
1858 ERROR("%s: TODO, edp_panel_power for this card!\n",
1859 __func__);
1860 // atombios_set_edp_panel_power(connector,
1861 // ATOM_TRANSMITTER_ACTION_POWER_ON);
1863 if (info.dceMajor >= 4) {
1864 encoder_dig_setup(connectorIndex, pll->pixelClock,
1865 ATOM_ENCODER_CMD_DP_VIDEO_OFF);
1867 // dp link train
1868 dp_link_train(crtcID);
1869 if (info.dceMajor >= 4) {
1870 encoder_dig_setup(connectorIndex, pll->pixelClock,
1871 ATOM_ENCODER_CMD_DP_VIDEO_ON);
1873 // not sure what AtomBIOS table/command sets this
1874 // register, but it's required to get the video output
1875 Write32(OUT, AVIVO_DP_VID_STREAM_CNTL, 0x201);
1877 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1878 transmitter_dig_setup(connectorIndex, pll->pixelClock,
1879 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON);
1881 break;
1882 case B_DPMS_STAND_BY:
1883 case B_DPMS_SUSPEND:
1884 case B_DPMS_OFF:
1885 if ((info.chipsetFlags & CHIP_APU) != 0 || info.dceMajor >= 5) {
1886 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1887 ATOM_TRANSMITTER_ACTION_DISABLE);
1888 } else {
1889 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1890 ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT);
1891 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
1892 ATOM_TRANSMITTER_ACTION_DISABLE);
1893 encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_DISABLE);
1895 if (connector_is_dp(connectorIndex)) {
1896 if (info.dceMajor >= 4) {
1897 encoder_dig_setup(connectorIndex, pll->pixelClock,
1898 ATOM_ENCODER_CMD_DP_VIDEO_OFF);
1899 #if 0
1900 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1901 atombios_set_edp_panel_power(connector,
1902 ATOM_TRANSMITTER_ACTION_POWER_OFF);
1903 radeon_dig_connector->edp_on = false;
1904 #endif
1907 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1908 transmitter_dig_setup(connectorIndex, pll->pixelClock,
1909 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF);
1911 break;
1916 void
1917 encoder_dpms_set_external(uint8 crtcID, int mode)
1919 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false");
1921 radeon_shared_info &info = *gInfo->shared_info;
1922 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1924 switch (mode) {
1925 case B_DPMS_ON:
1926 if ((info.chipsetFlags & CHIP_APU) != 0) {
1927 encoder_external_setup(connectorIndex,
1928 EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
1929 encoder_external_setup(connectorIndex,
1930 EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
1931 } else
1932 encoder_external_setup(connectorIndex, ATOM_ENABLE);
1934 break;
1935 case B_DPMS_STAND_BY:
1936 case B_DPMS_SUSPEND:
1937 case B_DPMS_OFF:
1938 if ((info.chipsetFlags & CHIP_APU) != 0) {
1939 encoder_external_setup(connectorIndex,
1940 EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
1941 encoder_external_setup(connectorIndex,
1942 EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
1943 } else
1944 encoder_external_setup(connectorIndex, ATOM_DISABLE);
1946 break;
1951 void
1952 encoder_dpms_set_dvo(uint8 crtcID, int mode)
1954 ERROR("%s: TODO, dvo encoder dpms stub\n", __func__);
1958 void
1959 encoder_output_lock(bool lock)
1961 TRACE("%s: %s\n", __func__, lock ? "true" : "false");
1962 uint32 biosScratch6 = Read32(OUT, R600_SCRATCH_REG6);
1964 if (lock) {
1965 biosScratch6 |= ATOM_S6_CRITICAL_STATE;
1966 biosScratch6 &= ~ATOM_S6_ACC_MODE;
1967 } else {
1968 biosScratch6 &= ~ATOM_S6_CRITICAL_STATE;
1969 biosScratch6 |= ATOM_S6_ACC_MODE;
1972 Write32(OUT, R600_SCRATCH_REG6, biosScratch6);
1975 static const char* encoder_name_matrix[] = {
1976 "NONE",
1977 "Internal Radeon LVDS",
1978 "Internal Radeon TMDS1",
1979 "Internal Radeon TMDS2",
1980 "Internal Radeon DAC1",
1981 "Internal Radeon DAC2 (TV)",
1982 "Internal Radeon SDVOA",
1983 "Internal Radeon SDVOB",
1984 "External 3rd party SI170B",
1985 "External 3rd party CH7303",
1986 "External 3rd party CH7301",
1987 "Internal Radeon DVO1",
1988 "External 3rd party SDVOA",
1989 "External 3rd party SDVOB",
1990 "External 3rd party TITFP513",
1991 "Internal LVTM1",
1992 "External 3rd party VT1623",
1993 "External HDMI SI1930",
1994 "Internal HDMI",
1995 "Internal Kaleidoscope TMDS1",
1996 "Internal Kaleidoscope DVO1",
1997 "Internal Kaleidoscope DAC1",
1998 "Internal Kaleidoscope DAC2",
1999 "External Kaleidoscope SI178",
2000 "MVPU FPGA",
2001 "Internal Kaleidoscope DDI",
2002 "External Kaleidoscope VT1625",
2003 "External Kaleidoscope HDMI SI1932",
2004 "External Kaleidoscope DP AN9801",
2005 "External Kaleidoscope DP DP501",
2006 "Internal Kaleidoscope UNIPHY",
2007 "Internal Kaleidoscope LVTMA",
2008 "Internal Kaleidoscope UNIPHY1",
2009 "Internal Kaleidoscope UNIPHY2",
2010 "External Nutmeg Bridge",
2011 "External Travis Bridge",
2012 "Internal Kaleidoscope VCE"
2016 const char*
2017 encoder_name_lookup(uint32 encoderID) {
2018 if (encoderID < B_COUNT_OF(encoder_name_matrix))
2019 return encoder_name_matrix[encoderID];
2020 else
2021 return "Unknown";
2025 uint32
2026 encoder_object_lookup(uint32 connectorFlags, uint8 dacID)
2028 // used on older cards to take a guess at the encoder
2029 // object
2031 radeon_shared_info &info = *gInfo->shared_info;
2033 uint32 ret = 0;
2035 switch (connectorFlags) {
2036 case ATOM_DEVICE_CRT1_SUPPORT:
2037 case ATOM_DEVICE_TV1_SUPPORT:
2038 case ATOM_DEVICE_TV2_SUPPORT:
2039 case ATOM_DEVICE_CRT2_SUPPORT:
2040 case ATOM_DEVICE_CV_SUPPORT:
2041 switch (dacID) {
2042 case 1:
2043 if ((info.chipsetID == RADEON_RS400)
2044 || (info.chipsetID == RADEON_RS480))
2045 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
2046 else if (info.chipsetID >= RADEON_RS600)
2047 ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
2048 else
2049 ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
2050 break;
2051 case 2:
2052 if (info.chipsetID >= RADEON_RS600)
2053 ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
2054 else {
2055 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
2057 break;
2058 case 3: // external dac
2059 if (info.chipsetID >= RADEON_RS600)
2060 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
2061 else
2062 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2063 break;
2065 break;
2066 case ATOM_DEVICE_LCD1_SUPPORT:
2067 if (info.chipsetID >= RADEON_RS600)
2068 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
2069 else
2070 ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
2071 break;
2072 case ATOM_DEVICE_DFP1_SUPPORT:
2073 if ((info.chipsetID == RADEON_RS400)
2074 || (info.chipsetID == RADEON_RS480))
2075 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2076 else if (info.chipsetID >= RADEON_RS600)
2077 ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
2078 else
2079 ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
2080 break;
2081 case ATOM_DEVICE_LCD2_SUPPORT:
2082 case ATOM_DEVICE_DFP2_SUPPORT:
2083 if ((info.chipsetID == RADEON_RS600)
2084 || (info.chipsetID == RADEON_RS690)
2085 || (info.chipsetID == RADEON_RS740))
2086 ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
2087 else if (info.chipsetID >= RADEON_RS600)
2088 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
2089 else
2090 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2091 break;
2092 case ATOM_DEVICE_DFP3_SUPPORT:
2093 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
2094 break;
2097 return ret;
2101 uint32
2102 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags)
2104 switch (encoderID) {
2105 case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2106 case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2107 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2108 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2109 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2110 return VIDEO_ENCODER_LVDS;
2111 else
2112 return VIDEO_ENCODER_TMDS;
2113 break;
2114 case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2115 return VIDEO_ENCODER_DAC;
2116 case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2117 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2118 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2119 return VIDEO_ENCODER_TVDAC;
2120 case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2121 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2122 case ENCODER_OBJECT_ID_INTERNAL_DDI:
2123 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2124 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2125 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2126 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2127 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2128 return VIDEO_ENCODER_LVDS;
2129 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
2130 return VIDEO_ENCODER_DAC;
2131 else
2132 return VIDEO_ENCODER_TMDS;
2133 break;
2134 case ENCODER_OBJECT_ID_SI170B:
2135 case ENCODER_OBJECT_ID_CH7303:
2136 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2137 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2138 case ENCODER_OBJECT_ID_TITFP513:
2139 case ENCODER_OBJECT_ID_VT1623:
2140 case ENCODER_OBJECT_ID_HDMI_SI1930:
2141 case ENCODER_OBJECT_ID_TRAVIS:
2142 case ENCODER_OBJECT_ID_NUTMEG:
2143 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2144 return VIDEO_ENCODER_LVDS;
2145 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
2146 return VIDEO_ENCODER_DAC;
2147 else
2148 return VIDEO_ENCODER_TMDS;
2149 break;
2152 return VIDEO_ENCODER_NONE;
2156 bool
2157 encoder_is_external(uint32 encoderID)
2159 switch (encoderID) {
2160 case ENCODER_OBJECT_ID_SI170B:
2161 case ENCODER_OBJECT_ID_CH7303:
2162 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2163 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2164 case ENCODER_OBJECT_ID_TITFP513:
2165 case ENCODER_OBJECT_ID_VT1623:
2166 case ENCODER_OBJECT_ID_HDMI_SI1930:
2167 case ENCODER_OBJECT_ID_TRAVIS:
2168 case ENCODER_OBJECT_ID_NUTMEG:
2169 return true;
2172 return false;
2176 bool
2177 encoder_is_dp_bridge(uint32 encoderID)
2179 switch (encoderID) {
2180 case ENCODER_OBJECT_ID_TRAVIS:
2181 case ENCODER_OBJECT_ID_NUTMEG:
2182 return true;
2184 return false;