2 * Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Alexander von Gluck, kallisti5@unixzen.com
17 #include "accelerant.h"
18 #include "accelerant_protos.h"
19 #include "atombios-obsolete.h"
21 #include "connector.h"
23 #include "displayport.h"
29 extern "C" void _sPrintf(const char* format
, ...);
30 # define TRACE(x...) _sPrintf("radeon_hd: " x)
32 # define TRACE(x...) ;
35 #define ERROR(x...) _sPrintf("radeon_hd: " x)
41 TRACE("%s: called\n", __func__
);
42 radeon_shared_info
&info
= *gInfo
->shared_info
;
44 for (uint32 id
= 0; id
< ATOM_MAX_SUPPORTED_DEVICE
; id
++) {
45 if (gConnector
[id
]->valid
== false)
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
);
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
);
71 encoder_assign_crtc(uint8 crtcID
)
73 TRACE("%s\n", __func__
);
75 int index
= GetIndexIntoMasterTable(COMMAND
, SelectCRTC_Source
);
80 if (atom_parse_cmd_header(gAtomContext
, index
, &tableMajor
, &tableMinor
)
84 TRACE("%s: table %" B_PRIu8
".%" B_PRIu8
"\n", __func__
,
85 tableMajor
, tableMinor
);
87 uint16 connectorIndex
= gDisplay
[crtcID
]->connectorIndex
;
88 uint16 connectorFlags
= gConnector
[connectorIndex
]->flags
;
89 uint16 encoderID
= gConnector
[connectorIndex
]->encoder
.objectID
;
91 // Prepare AtomBIOS command arguments
92 union crtcSourceParam
{
93 SELECT_CRTC_SOURCE_PS_ALLOCATION v1
;
94 SELECT_CRTC_SOURCE_PARAMETERS_V2 v2
;
96 union crtcSourceParam args
;
97 memset(&args
, 0, sizeof(args
));
101 switch (tableMinor
) {
104 args
.v1
.ucCRTC
= crtcID
;
106 case ENCODER_OBJECT_ID_INTERNAL_TMDS1
:
107 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1
:
108 args
.v1
.ucDevice
= ATOM_DEVICE_DFP1_INDEX
;
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
;
116 args
.v1
.ucDevice
= ATOM_DEVICE_DFP3_INDEX
;
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
;
123 case ENCODER_OBJECT_ID_INTERNAL_DAC1
:
124 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1
:
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
;
132 args
.v1
.ucDevice
= ATOM_DEVICE_CRT1_INDEX
;
134 case ENCODER_OBJECT_ID_INTERNAL_DAC2
:
135 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2
:
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
;
143 args
.v1
.ucDevice
= ATOM_DEVICE_CRT2_INDEX
;
148 args
.v2
.ucCRTC
= crtcID
;
150 = display_get_encoder_mode(connectorIndex
);
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
)) {
159 = ASIC_INT_DIG1_ENCODER_ID
;
163 = ASIC_INT_DIG2_ENCODER_ID
;
167 = ASIC_INT_DIG3_ENCODER_ID
;
171 = ASIC_INT_DIG4_ENCODER_ID
;
175 = ASIC_INT_DIG5_ENCODER_ID
;
179 = ASIC_INT_DIG6_ENCODER_ID
;
183 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1
:
184 args
.v2
.ucEncoderID
= ASIC_INT_DVO_ENCODER_ID
;
186 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1
:
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
;
194 args
.v2
.ucEncoderID
= ASIC_INT_DAC1_ENCODER_ID
;
196 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2
:
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
;
204 args
.v2
.ucEncoderID
= ASIC_INT_DAC2_ENCODER_ID
;
211 ERROR("%s: Unknown table version: %" B_PRIu8
".%" B_PRIu8
"\n",
212 __func__
, tableMajor
, tableMinor
);
216 atom_execute_table(gAtomContext
, index
, (uint32
*)&args
);
218 // update crtc encoder scratch register @ scratch 3
219 encoder_crtc_scratch(crtcID
);
224 encoder_pick_dig(uint32 connectorIndex
)
226 TRACE("%s: connector %" B_PRIu32
"\n", __func__
, connectorIndex
);
227 radeon_shared_info
&info
= *gInfo
->shared_info
;
228 uint32 encoderID
= gConnector
[connectorIndex
]->encoder
.objectID
;
230 // obtain assigned CRT
232 for (crtcID
= 0; crtcID
< MAX_DISPLAY
; crtcID
++) {
233 if (gDisplay
[crtcID
]->attached
!= true)
235 if (gDisplay
[crtcID
]->connectorIndex
== connectorIndex
)
239 bool linkB
= gConnector
[connectorIndex
]->encoder
.linkEnumeration
240 == GRAPH_OBJECT_ENUM_ID2
? true : false;
242 uint32 dceVersion
= (info
.dceMajor
* 100) + info
.dceMinor
;
244 if (dceVersion
>= 400) {
246 switch (info
.chipsetID
) {
248 return linkB
? 1 : 0;
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;
264 if (dceVersion
>= 302)
267 if (encoderID
== ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA
)
275 encoder_apply_quirks(uint8 crtcID
)
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
;
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);
294 encoder_mode_set(uint8 crtcID
)
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
;
302 // TODO: Should this be the adjusted pll or the original?
303 uint32 pixelClock
= pll
->pixelClock
;
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
);
317 encoder_tv_setup(connectorIndex
, pixelClock
, ATOM_DISABLE
);
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
);
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) {
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
);
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
);
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
);
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
);
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__
);
372 if (gConnector
[connectorIndex
]->encoderExternal
.valid
== true) {
373 if ((info
.chipsetFlags
& CHIP_APU
) != 0) {
375 encoder_external_setup(connectorIndex
,
376 EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP
);
378 encoder_external_setup(connectorIndex
, ATOM_ENABLE
);
382 encoder_apply_quirks(crtcID
);
387 encoder_tv_setup(uint32 connectorIndex
, uint32 pixelClock
, int command
)
389 TRACE("%s: connector %" B_PRIu32
", pixelClock: %" B_PRIu32
"\n", __func__
,
390 connectorIndex
, pixelClock
);
392 uint16 connectorFlags
= gConnector
[connectorIndex
]->flags
;
394 TV_ENCODER_CONTROL_PS_ALLOCATION args
;
395 memset(&args
, 0, sizeof(args
));
397 int index
= GetIndexIntoMasterTable(COMMAND
, TVEncoderControl
);
399 args
.sTVEncoder
.ucAction
= command
;
401 if ((connectorFlags
& ATOM_DEVICE_CV_SUPPORT
) != 0)
402 args
.sTVEncoder
.ucTvStandard
= ATOM_TV_CV
;
404 // TODO: we assume NTSC for now
405 args
.sTVEncoder
.ucTvStandard
= ATOM_TV_NTSC
;
408 args
.sTVEncoder
.usPixelClock
= B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
410 return atom_execute_table(gAtomContext
, index
, (uint32
*)&args
);
415 encoder_digital_setup(uint32 connectorIndex
, uint32 pixelClock
, int command
)
417 TRACE("%s: connector %" B_PRIu32
", pixelClock: %" B_PRIu32
"\n", __func__
,
418 connectorIndex
, pixelClock
);
421 uint16 connectorFlags
= gConnector
[connectorIndex
]->flags
;
423 switch (gConnector
[connectorIndex
]->encoder
.objectID
) {
424 case ENCODER_OBJECT_ID_INTERNAL_LVDS
:
425 index
= GetIndexIntoMasterTable(COMMAND
, LVDSEncoderControl
);
427 case ENCODER_OBJECT_ID_INTERNAL_TMDS1
:
428 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1
:
429 index
= GetIndexIntoMasterTable(COMMAND
, TMDS1EncoderControl
);
431 case ENCODER_OBJECT_ID_INTERNAL_LVTM1
:
432 if ((connectorFlags
& ATOM_DEVICE_LCD_SUPPORT
) != 0)
433 index
= GetIndexIntoMasterTable(COMMAND
, LVDSEncoderControl
);
435 index
= GetIndexIntoMasterTable(COMMAND
, TMDS2EncoderControl
);
443 if (atom_parse_cmd_header(gAtomContext
, index
, &tableMajor
, &tableMinor
)
445 ERROR("%s: cannot parse command table\n", __func__
);
449 uint32 lvdsFlags
= gConnector
[connectorIndex
]->lvdsFlags
;
452 if (gConnector
[connectorIndex
]->type
== VIDEO_CONNECTOR_HDMIA
453 || gConnector
[connectorIndex
]->type
== VIDEO_CONNECTOR_HDMIB
) {
457 // Prepare AtomBIOS command arguments
458 union lvdsEncoderControl
{
459 LVDS_ENCODER_CONTROL_PS_ALLOCATION v1
;
460 LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2
;
462 union lvdsEncoderControl args
;
463 memset(&args
, 0, sizeof(args
));
465 TRACE("%s: table %" B_PRIu8
".%" B_PRIu8
"\n", __func__
,
466 tableMajor
, tableMinor
);
468 switch (tableMajor
) {
471 switch (tableMinor
) {
474 args
.v1
.ucAction
= command
;
476 args
.v1
.ucMisc
|= PANEL_ENCODER_MISC_HDMI_TYPE
;
477 args
.v1
.usPixelClock
= B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
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
;
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
;
496 args
.v2
.ucAction
= command
;
497 if (tableMinor
== 3) {
498 //if (dig->coherent_mode)
499 // args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
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;
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) {
515 |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH
;
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) {
523 |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH
;
525 if (((lvdsFlags
>> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT
)
528 |= PANEL_ENCODER_TEMPORAL_LEVEL_4
;
533 // args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
534 if (pixelClock
> 165000)
535 args
.v2
.ucMisc
|= PANEL_ENCODER_MISC_DUAL
;
539 ERROR("%s: Unknown minor table version: %"
540 B_PRIu8
".%" B_PRIu8
"\n", __func__
,
541 tableMajor
, tableMinor
);
546 ERROR("%s: Unknown major table version: %" B_PRIu8
".%" B_PRIu8
"\n",
547 __func__
, tableMajor
, tableMinor
);
550 return atom_execute_table(gAtomContext
, index
, (uint32
*)&args
);
560 return PANEL_BPC_UNDEFINE;
562 return PANEL_6BIT_PER_COLOR;
564 return PANEL_8BIT_PER_COLOR;
566 return PANEL_10BIT_PER_COLOR;
568 return PANEL_12BIT_PER_COLOR;
570 return PANEL_16BIT_PER_COLOR;
573 return PANEL_8BIT_PER_COLOR
;
578 encoder_dig_setup(uint32 connectorIndex
, uint32 pixelClock
, int command
)
580 TRACE("%s\n", __func__
);
582 radeon_shared_info
&info
= *gInfo
->shared_info
;
583 connector_info
* connector
= gConnector
[connectorIndex
];
586 if (info
.dceMajor
>= 4)
587 index
= GetIndexIntoMasterTable(COMMAND
, DIGxEncoderControl
);
589 if (encoder_pick_dig(connectorIndex
))
590 index
= GetIndexIntoMasterTable(COMMAND
, DIG2EncoderControl
);
592 index
= GetIndexIntoMasterTable(COMMAND
, DIG1EncoderControl
);
599 if (atom_parse_cmd_header(gAtomContext
, index
, &tableMajor
, &tableMinor
)
601 ERROR("%s: cannot parse command table\n", __func__
);
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
;
613 union digEncoderControl args
;
614 memset(&args
, 0, sizeof(args
));
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
);
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
;
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
;
638 panelMode
= DP_PANEL_MODE_INTERNAL_DP2_MODE
;
641 panelMode
= DP_PANEL_MODE_INTERNAL_DP2_MODE
;
644 panelMode
= DP_PANEL_MODE_EXTERNAL_DP_MODE
;
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
);
652 panelMode
= DP_PANEL_MODE_INTERNAL_DP2_MODE
;
656 TRACE("%s: table %" B_PRIu8
".%" B_PRIu8
"\n", __func__
,
657 tableMajor
, tableMinor
);
659 dp_info
* dpInfo
= &gConnector
[connectorIndex
]->dpInfo
;
661 if (dpInfo
->valid
== true)
662 dpClock
= dpInfo
->linkRate
;
664 bool dualLink
= false;
665 if (connector
->type
== VIDEO_CONNECTOR_DVID
666 && pixelClock
> 165000) {
667 // TODO: Expand on this duallink code
671 uint32 encoderMode
= display_get_encoder_mode(connectorIndex
);
673 // Careful! The mapping of ucHPD_ID differs between atombios calls
674 uint16 hpdID
= connector_pick_atom_hpdid(connectorIndex
);
676 if (tableMajor
!= 1) {
677 ERROR("%s: Unknown table major!\n", __func__
);
680 switch (tableMinor
) {
682 args
.v1
.ucAction
= command
;
683 args
.v1
.usPixelClock
= B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
685 if (command
== ATOM_ENCODER_CMD_SETUP_PANEL_MODE
)
686 args
.v3
.ucPanelMode
= panelMode
;
688 args
.v1
.ucEncoderMode
= encoderMode
;
691 if (args
.v1
.ucEncoderMode
== ATOM_ENCODER_MODE_DP
692 || args
.v1
.ucEncoderMode
== ATOM_ENCODER_MODE_DP_MST
) {
693 args
.v1
.ucLaneNum
= dpInfo
->laneCount
;
695 args
.v1
.ucLaneNum
= 8;
697 args
.v1
.ucLaneNum
= 4;
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
;
705 switch (connector
->encoder
.objectID
) {
706 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY
:
707 args
.v1
.ucConfig
= ATOM_ENCODER_CONFIG_V2_TRANSMITTER1
;
709 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1
:
710 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA
:
711 args
.v1
.ucConfig
= ATOM_ENCODER_CONFIG_V2_TRANSMITTER2
;
713 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2
:
714 args
.v1
.ucConfig
= ATOM_ENCODER_CONFIG_V2_TRANSMITTER3
;
719 args
.v1
.ucConfig
|= ATOM_ENCODER_CONFIG_LINKB
;
721 args
.v1
.ucConfig
|= ATOM_ENCODER_CONFIG_LINKA
;
725 args
.v3
.ucAction
= command
;
726 args
.v3
.usPixelClock
= B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
728 if (command
== ATOM_ENCODER_CMD_SETUP_PANEL_MODE
)
729 args
.v3
.ucPanelMode
= panelMode
;
731 args
.v3
.ucEncoderMode
= encoderMode
;
733 if (args
.v3
.ucEncoderMode
== ATOM_ENCODER_MODE_DP
734 || args
.v3
.ucEncoderMode
== ATOM_ENCODER_MODE_DP_MST
) {
735 args
.v3
.ucLaneNum
= dpInfo
->laneCount
;
737 args
.v3
.ucLaneNum
= 8;
739 args
.v3
.ucLaneNum
= 4;
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
;
747 args
.v3
.acConfig
.ucDigSel
= encoder_pick_dig(connectorIndex
);
748 args
.v3
.ucBitPerColor
= encoder_get_bpc();
751 args
.v4
.ucAction
= command
;
752 args
.v4
.usPixelClock
= B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
754 if (command
== ATOM_ENCODER_CMD_SETUP_PANEL_MODE
)
755 args
.v4
.ucPanelMode
= panelMode
;
757 args
.v4
.ucEncoderMode
= encoderMode
;
759 if (args
.v4
.ucEncoderMode
== ATOM_ENCODER_MODE_DP
760 || args
.v4
.ucEncoderMode
== ATOM_ENCODER_MODE_DP_MST
) {
762 args
.v4
.ucLaneNum
= dpInfo
->laneCount
;
763 if (dpClock
== 270000) {
765 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ
;
766 } else if (dpClock
== 540000) {
768 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ
;
770 } else if (dualLink
) {
771 // DualLink, double the lane numbers
772 args
.v4
.ucLaneNum
= 8;
774 args
.v4
.ucLaneNum
= 4;
776 args
.v4
.acConfig
.ucDigSel
= digEncoderID
;
777 args
.v4
.ucBitPerColor
= encoder_get_bpc();
780 args
.v4
.ucHPD_ID
= 0;
782 args
.v4
.ucHPD_ID
= hpdID
+ 1;
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
;
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
;
799 args
.v5
.asStreamParam
.ucLaneNum
= 8;
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;
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
;
819 ERROR("%s: Unknown command: 0x%X\n", __func__
, command
);
823 ERROR("%s: unknown tableMinor!\n", __func__
);
827 status_t result
= atom_execute_table(gAtomContext
, index
, (uint32
*)&args
);
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);
841 encoder_external_setup(uint32 connectorIndex
, int command
)
843 TRACE("%s: connector %" B_PRIu32
"\n", __func__
, connectorIndex
);
845 encoder_info
* encoder
846 = &gConnector
[connectorIndex
]->encoder
;
847 encoder_info
* extEncoder
848 = &gConnector
[connectorIndex
]->encoderExternal
;
849 uint32 connectorFlags
= gConnector
[connectorIndex
]->flags
;
852 = &gConnector
[connectorIndex
]->dpInfo
;
854 if (extEncoder
->valid
!= true) {
855 ERROR("%s: connector %" B_PRIu32
" doesn't have a valid "
856 "external encoder!", __func__
, connectorIndex
);
863 int index
= GetIndexIntoMasterTable(COMMAND
, ExternalEncoderControl
);
864 if (atom_parse_cmd_header(gAtomContext
, index
, &tableMajor
, &tableMinor
)
866 ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__
);
870 // Prepare AtomBIOS command arguments
871 union externalEncoderControl
{
872 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1
;
873 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3
;
875 union externalEncoderControl args
;
876 memset(&args
, 0, sizeof(args
));
878 int connectorObjectID
879 = (gConnector
[connectorIndex
]->objectID
& OBJECT_ID_MASK
)
882 uint32 pixelClock
= encoder
->pll
.pixelClock
;
884 TRACE("%s: table %" B_PRIu8
".%" B_PRIu8
"\n", __func__
,
885 tableMajor
, tableMinor
);
886 switch (tableMajor
) {
888 // no options needed on table 1.x
891 switch (tableMinor
) {
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
);
900 if (connector_is_dp(connectorIndex
)) {
901 if (dpInfo
->linkRate
== 270000) {
902 args
.v1
.sDigEncoder
.ucConfig
903 |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ
;
905 args
.v1
.sDigEncoder
.ucLaneNum
907 } else if (pixelClock
> 165000) {
908 args
.v1
.sDigEncoder
.ucLaneNum
= 8;
910 args
.v1
.sDigEncoder
.ucLaneNum
= 4;
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
);
920 args
.v3
.sExtEncoder
.usPixelClock
921 = B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
924 args
.v3
.sExtEncoder
.ucEncoderMode
925 = display_get_encoder_mode(connectorIndex
);
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
;
935 args
.v1
.sDigEncoder
.ucLaneNum
937 } else if (pixelClock
> 165000) {
938 args
.v3
.sExtEncoder
.ucLaneNum
= 8;
940 args
.v3
.sExtEncoder
.ucLaneNum
= 4;
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
;
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
;
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
;
961 // TODO: don't set statically
962 uint32 bitsPerColor
= 8;
963 switch (bitsPerColor
) {
965 args
.v3
.sExtEncoder
.ucBitPerColor
966 = PANEL_BPC_UNDEFINE
;
969 args
.v3
.sExtEncoder
.ucBitPerColor
970 = PANEL_6BIT_PER_COLOR
;
974 args
.v3
.sExtEncoder
.ucBitPerColor
975 = PANEL_8BIT_PER_COLOR
;
978 args
.v3
.sExtEncoder
.ucBitPerColor
979 = PANEL_10BIT_PER_COLOR
;
982 args
.v3
.sExtEncoder
.ucBitPerColor
983 = PANEL_12BIT_PER_COLOR
;
986 args
.v3
.sExtEncoder
.ucBitPerColor
987 = PANEL_16BIT_PER_COLOR
;
993 ERROR("%s: Unknown table minor version: "
994 "%" B_PRIu8
".%" B_PRIu8
"\n", __func__
,
995 tableMajor
, tableMinor
);
1000 ERROR("%s: Unknown table major version: "
1001 "%" B_PRIu8
".%" B_PRIu8
"\n", __func__
,
1002 tableMajor
, tableMinor
);
1006 return atom_execute_table(gAtomContext
, index
, (uint32
*)&args
);
1011 encoder_analog_setup(uint32 connectorIndex
, uint32 pixelClock
, int command
)
1013 TRACE("%s: connector %" B_PRIu32
", pixelClock: %" B_PRIu32
"\n", __func__
,
1014 connectorIndex
, pixelClock
);
1016 uint32 connectorFlags
= gConnector
[connectorIndex
]->flags
;
1019 DAC_ENCODER_CONTROL_PS_ALLOCATION args
;
1020 memset(&args
, 0, sizeof(args
));
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
);
1027 case ENCODER_OBJECT_ID_INTERNAL_DAC2
:
1028 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2
:
1029 index
= GetIndexIntoMasterTable(COMMAND
, DAC2EncoderControl
);
1033 args
.ucAction
= command
;
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
;
1040 TRACE("%s: TODO, hardcoded NTSC TV support\n", __func__
);
1042 // NTSC, NTSC_J, PAL 60
1043 args
.ucDacStandard
= ATOM_DAC1_NTSC
;
1045 // PAL, SCART. SECAM, PAL_CN
1046 args
.ucDacStandard
= ATOM_DAC1_PAL
;
1050 args
.usPixelClock
= B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
1052 return atom_execute_table(gAtomContext
, index
, (uint32
*)&args
);
1057 encoder_analog_load_detect(uint32 connectorIndex
)
1059 TRACE("%s: connector %" B_PRIu32
"\n", __func__
, connectorIndex
);
1061 if (gConnector
[connectorIndex
]->encoderExternal
.valid
== true)
1062 return encoder_dig_load_detect(connectorIndex
);
1064 return encoder_dac_load_detect(connectorIndex
);
1069 encoder_dac_load_detect(uint32 connectorIndex
)
1071 TRACE("%s: connector %" B_PRIu32
"\n", __func__
, connectorIndex
);
1073 uint32 connectorFlags
= gConnector
[connectorIndex
]->flags
;
1074 uint32 encoderID
= gConnector
[connectorIndex
]->encoder
.objectID
;
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
);
1084 // *** tell the card we want to do a DAC detection
1086 DAC_LOAD_DETECTION_PS_ALLOCATION args
;
1087 int index
= GetIndexIntoMasterTable(COMMAND
, DAC_LoadDetection
);
1091 memset(&args
, 0, sizeof(args
));
1093 if (atom_parse_cmd_header(gAtomContext
, index
, &tableMajor
, &tableMinor
)
1095 ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n",
1100 args
.sDacload
.ucMisc
= 0;
1102 if (encoderID
== ENCODER_OBJECT_ID_INTERNAL_DAC1
1103 || encoderID
== ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1
) {
1104 args
.sDacload
.ucDacType
= ATOM_DAC_A
;
1106 args
.sDacload
.ucDacType
= ATOM_DAC_B
;
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
);
1114 uint32 biosScratch0
= Read32(OUT
, R600_SCRATCH_REG0
);
1116 if ((biosScratch0
& ATOM_S0_CRT1_MASK
) != 0)
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
);
1124 uint32 biosScratch0
= Read32(OUT
, R600_SCRATCH_REG0
);
1126 if ((biosScratch0
& ATOM_S0_CRT2_MASK
) != 0)
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
);
1136 uint32 biosScratch0
= Read32(OUT
, R600_SCRATCH_REG0
);
1138 if ((biosScratch0
& (ATOM_S0_CV_MASK
| ATOM_S0_CV_MASK_A
)) != 0)
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
);
1148 uint32 biosScratch0
= Read32(OUT
, R600_SCRATCH_REG0
);
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 */
1164 encoder_dig_load_detect(uint32 connectorIndex
)
1166 TRACE("%s: connector %" B_PRIu32
"\n", __func__
, connectorIndex
);
1167 radeon_shared_info
&info
= *gInfo
->shared_info
;
1169 if (info
.dceMajor
< 4) {
1170 ERROR("%s: Strange: External DIG encoder on DCE < 4?\n", __func__
);
1174 encoder_external_setup(connectorIndex
,
1175 EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION
);
1177 uint32 biosScratch0
= Read32(OUT
, R600_SCRATCH_REG0
);
1179 uint32 connectorFlags
= gConnector
[connectorIndex
]->flags
;
1181 if ((connectorFlags
& ATOM_DEVICE_CRT1_SUPPORT
) != 0)
1182 if ((biosScratch0
& ATOM_S0_CRT1_MASK
) != 0)
1184 if ((connectorFlags
& ATOM_DEVICE_CRT2_SUPPORT
) != 0)
1185 if ((biosScratch0
& ATOM_S0_CRT2_MASK
) != 0)
1187 if ((connectorFlags
& ATOM_DEVICE_CV_SUPPORT
) != 0)
1188 if ((biosScratch0
& (ATOM_S0_CV_MASK
| ATOM_S0_CV_MASK_A
)) != 0)
1190 if ((connectorFlags
& ATOM_DEVICE_TV1_SUPPORT
) != 0) {
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 */
1204 transmitter_dig_setup(uint32 connectorIndex
, uint32 pixelClock
,
1205 uint8 laneNumber
, uint8 laneSet
, int command
)
1207 TRACE("%s: connector %" B_PRIu32
", pixelClock: %" B_PRIu32
"\n", __func__
,
1208 connectorIndex
, pixelClock
);
1210 uint16 encoderID
= gConnector
[connectorIndex
]->encoder
.objectID
;
1212 switch (encoderID
) {
1213 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1
:
1214 index
= GetIndexIntoMasterTable(COMMAND
, DVOOutputControl
);
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
);
1221 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA
:
1222 index
= GetIndexIntoMasterTable(COMMAND
, LVTMATransmitterControl
);
1225 ERROR("%s: BUG: dig setup run on non-dig encoder!\n", __func__
);
1230 ERROR("%s: GetIndexIntoMasterTable failed!\n", __func__
);
1237 if (atom_parse_cmd_header(gAtomContext
, index
, &tableMajor
, &tableMinor
)
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
;
1250 union digTransmitterControl args
;
1251 memset(&args
, 0, sizeof(args
));
1253 TRACE("%s: table %" B_PRIu8
".%" B_PRIu8
"\n", __func__
,
1254 tableMajor
, tableMinor
);
1256 int connectorObjectID
1257 = (gConnector
[connectorIndex
]->objectID
& OBJECT_ID_MASK
)
1259 uint32 encoderObjectID
= gConnector
[connectorIndex
]->encoder
.objectID
;
1260 uint32 digEncoderID
= encoder_pick_dig(connectorIndex
);
1262 pll_info
* pll
= &gConnector
[connectorIndex
]->encoder
.pll
;
1264 bool isDP
= connector_is_dp(connectorIndex
);
1265 bool linkB
= gConnector
[connectorIndex
]->encoder
.linkEnumeration
1266 == GRAPH_OBJECT_ENUM_ID2
? true : false;
1268 dp_info
* dpInfo
= &gConnector
[connectorIndex
]->dpInfo
;
1271 int dpLaneCount
= 0;
1272 if (dpInfo
->valid
== true) {
1273 dpClock
= dpInfo
->linkRate
;
1274 dpLaneCount
= dpInfo
->laneCount
;
1277 switch (tableMajor
) {
1279 switch (tableMinor
) {
1281 args
.v1
.ucAction
= command
;
1282 if (command
== ATOM_TRANSMITTER_ACTION_INIT
) {
1284 = B_HOST_TO_LENDIAN_INT16(connectorObjectID
);
1286 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH
) {
1287 args
.v1
.asMode
.ucLaneSel
= laneNumber
;
1288 args
.v1
.asMode
.ucLaneSet
= laneSet
;
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);
1297 args
.v1
.usPixelClock
1298 = B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
1302 args
.v1
.ucConfig
= ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL
;
1304 if (digEncoderID
> 0) {
1306 |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER
;
1309 |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER
;
1312 // TODO: IGP DIG Transmitter setup
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)
1319 |= ATOM_TRANSMITTER_CONFIG_LANE_0_3
;
1320 else if (igp_lane_info
& 0x2)
1322 |= ATOM_TRANSMITTER_CONFIG_LANE_4_7
;
1323 else if (igp_lane_info
& 0x4)
1325 |= ATOM_TRANSMITTER_CONFIG_LANE_8_11
;
1326 else if (igp_lane_info
& 0x8)
1328 |= ATOM_TRANSMITTER_CONFIG_LANE_12_15
;
1330 if (igp_lane_info
& 0x3)
1332 |= ATOM_TRANSMITTER_CONFIG_LANE_0_7
;
1333 else if (igp_lane_info
& 0xc)
1335 |= ATOM_TRANSMITTER_CONFIG_LANE_8_15
;
1341 args
.v1
.ucConfig
|= ATOM_TRANSMITTER_CONFIG_LINKB
;
1343 args
.v1
.ucConfig
|= ATOM_TRANSMITTER_CONFIG_LINKA
;
1346 args
.v1
.ucConfig
|= ATOM_TRANSMITTER_CONFIG_COHERENT
;
1347 else if ((gConnector
[connectorIndex
]->flags
1348 & ATOM_DEVICE_DFP_SUPPORT
) != 0) {
1350 // if coherentMode, i've only ever seen it true
1352 |= ATOM_TRANSMITTER_CONFIG_COHERENT
;
1354 if (pixelClock
> 165000) {
1356 |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK
;
1361 args
.v2
.ucAction
= command
;
1362 if (command
== ATOM_TRANSMITTER_ACTION_INIT
) {
1364 = B_HOST_TO_LENDIAN_INT16(connectorObjectID
);
1366 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH
) {
1367 args
.v2
.asMode
.ucLaneSel
= laneNumber
;
1368 args
.v2
.asMode
.ucLaneSet
= laneSet
;
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);
1377 args
.v2
.usPixelClock
1378 = B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
1381 args
.v2
.acConfig
.ucEncoderSel
= digEncoderID
;
1383 args
.v2
.acConfig
.ucLinkSel
= 1;
1385 switch (encoderObjectID
) {
1386 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY
:
1387 args
.v2
.acConfig
.ucTransmitterSel
= 0;
1389 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1
:
1390 args
.v2
.acConfig
.ucTransmitterSel
= 1;
1392 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2
:
1393 args
.v2
.acConfig
.ucTransmitterSel
= 2;
1398 args
.v2
.acConfig
.fCoherentMode
= 1;
1399 args
.v2
.acConfig
.fDPConnector
= 1;
1400 } else if ((gConnector
[connectorIndex
]->flags
1401 & ATOM_DEVICE_DFP_SUPPORT
) != 0) {
1403 // if coherentMode, i've only ever seen it true
1404 args
.v2
.acConfig
.fCoherentMode
= 1;
1407 if (pixelClock
> 165000)
1408 args
.v2
.acConfig
.fDualLinkConnector
= 1;
1412 args
.v3
.ucAction
= command
;
1413 if (command
== ATOM_TRANSMITTER_ACTION_INIT
) {
1415 = B_HOST_TO_LENDIAN_INT16(connectorObjectID
);
1417 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH
) {
1418 args
.v3
.asMode
.ucLaneSel
= laneNumber
;
1419 args
.v3
.asMode
.ucLaneSet
= laneSet
;
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);
1428 args
.v3
.usPixelClock
1429 = B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
1434 args
.v3
.ucLaneNum
= dpLaneCount
;
1435 else if (pixelClock
> 165000)
1436 args
.v3
.ucLaneNum
= 8;
1438 args
.v3
.ucLaneNum
= 4;
1441 args
.v3
.acConfig
.ucLinkSel
= 1;
1442 if (digEncoderID
& 1)
1443 args
.v3
.acConfig
.ucEncoderSel
= 1;
1445 // Select the PLL for the PHY
1446 // DP PHY to be clocked from external src if possible
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
1453 args
.v3
.acConfig
.ucRefClkSource
= pll
->id
;
1455 switch (encoderObjectID
) {
1456 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY
:
1457 args
.v3
.acConfig
.ucTransmitterSel
= 0;
1459 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1
:
1460 args
.v3
.acConfig
.ucTransmitterSel
= 1;
1462 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2
:
1463 args
.v3
.acConfig
.ucTransmitterSel
= 2;
1468 args
.v3
.acConfig
.fCoherentMode
= 1;
1469 else if ((gConnector
[connectorIndex
]->flags
1470 & ATOM_DEVICE_DFP_SUPPORT
) != 0) {
1472 // if coherentMode, i've only ever seen it true
1473 args
.v3
.acConfig
.fCoherentMode
= 1;
1475 if (pixelClock
> 165000)
1476 args
.v3
.acConfig
.fDualLinkConnector
= 1;
1480 args
.v4
.ucAction
= command
;
1481 if (command
== ATOM_TRANSMITTER_ACTION_INIT
) {
1483 = B_HOST_TO_LENDIAN_INT16(connectorObjectID
);
1485 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH
) {
1486 args
.v4
.asMode
.ucLaneSel
= laneNumber
;
1487 args
.v4
.asMode
.ucLaneSet
= laneSet
;
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);
1496 args
.v4
.usPixelClock
1497 = B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
1502 args
.v4
.ucLaneNum
= dpLaneCount
;
1503 else if (pixelClock
> 165000)
1504 args
.v4
.ucLaneNum
= 8;
1506 args
.v4
.ucLaneNum
= 4;
1509 args
.v4
.acConfig
.ucLinkSel
= 1;
1510 if (digEncoderID
& 1)
1511 args
.v4
.acConfig
.ucEncoderSel
= 1;
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
1517 if (gInfo
->dpExternalClock
> 0) {
1518 args
.v4
.acConfig
.ucRefClkSource
1519 = ENCODER_REFCLK_SRC_EXTCLK
;
1521 args
.v4
.acConfig
.ucRefClkSource
1522 = ENCODER_REFCLK_SRC_DCPLL
;
1525 args
.v4
.acConfig
.ucRefClkSource
= pll
->id
;
1527 switch (encoderObjectID
) {
1528 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY
:
1529 args
.v4
.acConfig
.ucTransmitterSel
= 0;
1531 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1
:
1532 args
.v4
.acConfig
.ucTransmitterSel
= 1;
1534 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2
:
1535 args
.v4
.acConfig
.ucTransmitterSel
= 2;
1540 args
.v4
.acConfig
.fCoherentMode
= 1;
1541 else if ((gConnector
[connectorIndex
]->flags
1542 & ATOM_DEVICE_DFP_SUPPORT
) != 0) {
1544 // if coherentMode, i've only ever seen it true
1545 args
.v4
.acConfig
.fCoherentMode
= 1;
1547 if (pixelClock
> 165000)
1548 args
.v4
.acConfig
.fDualLinkConnector
= 1;
1552 args
.v5
.ucAction
= command
;
1556 = B_HOST_TO_LENDIAN_INT16(dpClock
/ 10);
1559 = B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
1561 switch (encoderObjectID
) {
1562 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY
:
1564 args
.v5
.ucPhyId
= ATOM_PHY_ID_UNIPHYB
;
1566 args
.v5
.ucPhyId
= ATOM_PHY_ID_UNIPHYA
;
1568 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1
:
1570 args
.v5
.ucPhyId
= ATOM_PHY_ID_UNIPHYD
;
1572 args
.v5
.ucPhyId
= ATOM_PHY_ID_UNIPHYC
;
1574 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2
:
1576 args
.v5
.ucPhyId
= ATOM_PHY_ID_UNIPHYF
;
1578 args
.v5
.ucPhyId
= ATOM_PHY_ID_UNIPHYE
;
1582 args
.v5
.ucLaneNum
= dpLaneCount
;
1583 } else if (pixelClock
>= 165000) {
1584 args
.v5
.ucLaneNum
= 8;
1586 args
.v5
.ucLaneNum
= 4;
1589 args
.v5
.ucConnObjId
= connectorObjectID
;
1591 if (command
!= ATOM_TRANSMITTER_ACTION_INIT
) {
1592 // not used on INIT and display_get_encoder_mode
1593 // unavailable until displays are probed.
1595 = display_get_encoder_mode(connectorIndex
);
1598 if (isDP
&& gInfo
->dpExternalClock
) {
1599 args
.v5
.asConfig
.ucPhyClkSrcId
1600 = ENCODER_REFCLK_SRC_EXTCLK
;
1602 args
.v5
.asConfig
.ucPhyClkSrcId
= pll
->id
;
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;
1614 // TODO: hpd_id, for now RADEON_HPD_NONE.
1615 args
.v5
.asConfig
.ucHPDSel
= 0;
1617 args
.v5
.ucDigEncoderSel
= 1 << digEncoderID
;
1618 args
.v5
.ucDPLaneSet
= laneSet
;
1621 args
.v6
.ucAction
= command
;
1624 = B_HOST_TO_LENDIAN_INT16(dpClock
/ 10);
1627 = B_HOST_TO_LENDIAN_INT16(pixelClock
/ 10);
1629 switch (encoderObjectID
) {
1630 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY
:
1632 args
.v6
.ucPhyId
= ATOM_PHY_ID_UNIPHYB
;
1634 args
.v6
.ucPhyId
= ATOM_PHY_ID_UNIPHYA
;
1636 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1
:
1638 args
.v6
.ucPhyId
= ATOM_PHY_ID_UNIPHYD
;
1640 args
.v6
.ucPhyId
= ATOM_PHY_ID_UNIPHYC
;
1642 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2
:
1644 args
.v6
.ucPhyId
= ATOM_PHY_ID_UNIPHYF
;
1646 args
.v6
.ucPhyId
= ATOM_PHY_ID_UNIPHYE
;
1648 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3
:
1649 args
.v6
.ucPhyId
= ATOM_PHY_ID_UNIPHYG
;
1653 args
.v6
.ucLaneNum
= dpLaneCount
;
1654 else if (pixelClock
> 165000)
1655 args
.v6
.ucLaneNum
= 8;
1657 args
.v6
.ucLaneNum
= 4;
1659 args
.v6
.ucConnObjId
= connectorObjectID
;
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.
1667 = display_get_encoder_mode(connectorIndex
);
1669 // TODO: hpd_id, for now RADEON_HPD_NONE.
1670 args
.v6
.ucHPDSel
= 0;
1672 args
.v6
.ucDigEncoderSel
= 1 << digEncoderID
;
1675 ERROR("%s: unknown table version\n", __func__
);
1679 ERROR("%s: unknown table version\n", __func__
);
1682 return atom_execute_table(gAtomContext
, index
, (uint32
*)&args
);
1687 encoder_crtc_scratch(uint8 crtcID
)
1689 TRACE("%s: display %" B_PRIu8
"\n", __func__
, crtcID
);
1691 uint32 connectorIndex
= gDisplay
[crtcID
]->connectorIndex
;
1692 uint32 connectorFlags
= gConnector
[connectorIndex
]->flags
;
1695 uint32 biosScratch3
= Read32(OUT
, R600_SCRATCH_REG3
);
1697 if ((connectorFlags
& ATOM_DEVICE_TV1_SUPPORT
) != 0) {
1698 biosScratch3
&= ~ATOM_S3_TV1_CRTC_ACTIVE
;
1699 biosScratch3
|= (crtcID
<< 18);
1701 if ((connectorFlags
& ATOM_DEVICE_CV_SUPPORT
) != 0) {
1702 biosScratch3
&= ~ATOM_S3_CV_CRTC_ACTIVE
;
1703 biosScratch3
|= (crtcID
<< 24);
1705 if ((connectorFlags
& ATOM_DEVICE_CRT1_SUPPORT
) != 0) {
1706 biosScratch3
&= ~ATOM_S3_CRT1_CRTC_ACTIVE
;
1707 biosScratch3
|= (crtcID
<< 16);
1709 if ((connectorFlags
& ATOM_DEVICE_CRT2_SUPPORT
) != 0) {
1710 biosScratch3
&= ~ATOM_S3_CRT2_CRTC_ACTIVE
;
1711 biosScratch3
|= (crtcID
<< 20);
1713 if ((connectorFlags
& ATOM_DEVICE_LCD1_SUPPORT
) != 0) {
1714 biosScratch3
&= ~ATOM_S3_LCD1_CRTC_ACTIVE
;
1715 biosScratch3
|= (crtcID
<< 17);
1717 if ((connectorFlags
& ATOM_DEVICE_DFP1_SUPPORT
) != 0) {
1718 biosScratch3
&= ~ATOM_S3_DFP1_CRTC_ACTIVE
;
1719 biosScratch3
|= (crtcID
<< 19);
1721 if ((connectorFlags
& ATOM_DEVICE_DFP2_SUPPORT
) != 0) {
1722 biosScratch3
&= ~ATOM_S3_DFP2_CRTC_ACTIVE
;
1723 biosScratch3
|= (crtcID
<< 23);
1725 if ((connectorFlags
& ATOM_DEVICE_DFP3_SUPPORT
) != 0) {
1726 biosScratch3
&= ~ATOM_S3_DFP3_CRTC_ACTIVE
;
1727 biosScratch3
|= (crtcID
<< 25);
1731 Write32(OUT
, R600_SCRATCH_REG3
, biosScratch3
);
1736 encoder_dpms_scratch(uint8 crtcID
, bool power
)
1738 TRACE("%s: display %" B_PRIu8
"\n", __func__
, crtcID
);
1740 uint32 connectorIndex
= gDisplay
[crtcID
]->connectorIndex
;
1741 uint32 connectorFlags
= gConnector
[connectorIndex
]->flags
;
1744 uint32 biosScratch2
= Read32(OUT
, R600_SCRATCH_REG2
);
1746 if ((connectorFlags
& ATOM_DEVICE_TV1_SUPPORT
) != 0) {
1748 biosScratch2
&= ~ATOM_S2_TV1_DPMS_STATE
;
1750 biosScratch2
|= ATOM_S2_TV1_DPMS_STATE
;
1752 if ((connectorFlags
& ATOM_DEVICE_CV_SUPPORT
) != 0) {
1754 biosScratch2
&= ~ATOM_S2_CV_DPMS_STATE
;
1756 biosScratch2
|= ATOM_S2_CV_DPMS_STATE
;
1758 if ((connectorFlags
& ATOM_DEVICE_CRT1_SUPPORT
) != 0) {
1760 biosScratch2
&= ~ATOM_S2_CRT1_DPMS_STATE
;
1762 biosScratch2
|= ATOM_S2_CRT1_DPMS_STATE
;
1764 if ((connectorFlags
& ATOM_DEVICE_CRT2_SUPPORT
) != 0) {
1766 biosScratch2
&= ~ATOM_S2_CRT2_DPMS_STATE
;
1768 biosScratch2
|= ATOM_S2_CRT2_DPMS_STATE
;
1770 if ((connectorFlags
& ATOM_DEVICE_LCD1_SUPPORT
) != 0) {
1772 biosScratch2
&= ~ATOM_S2_LCD1_DPMS_STATE
;
1774 biosScratch2
|= ATOM_S2_LCD1_DPMS_STATE
;
1776 if ((connectorFlags
& ATOM_DEVICE_DFP1_SUPPORT
) != 0) {
1778 biosScratch2
&= ~ATOM_S2_DFP1_DPMS_STATE
;
1780 biosScratch2
|= ATOM_S2_DFP1_DPMS_STATE
;
1782 if ((connectorFlags
& ATOM_DEVICE_DFP2_SUPPORT
) != 0) {
1784 biosScratch2
&= ~ATOM_S2_DFP2_DPMS_STATE
;
1786 biosScratch2
|= ATOM_S2_DFP2_DPMS_STATE
;
1788 if ((connectorFlags
& ATOM_DEVICE_DFP3_SUPPORT
) != 0) {
1790 biosScratch2
&= ~ATOM_S2_DFP3_DPMS_STATE
;
1792 biosScratch2
|= ATOM_S2_DFP3_DPMS_STATE
;
1794 if ((connectorFlags
& ATOM_DEVICE_DFP4_SUPPORT
) != 0) {
1796 biosScratch2
&= ~ATOM_S2_DFP4_DPMS_STATE
;
1798 biosScratch2
|= ATOM_S2_DFP4_DPMS_STATE
;
1800 if ((connectorFlags
& ATOM_DEVICE_DFP5_SUPPORT
) != 0) {
1802 biosScratch2
&= ~ATOM_S2_DFP5_DPMS_STATE
;
1804 biosScratch2
|= ATOM_S2_DFP5_DPMS_STATE
;
1806 Write32(OUT
, R600_SCRATCH_REG2
, biosScratch2
);
1811 encoder_dpms_set(uint8 crtcID
, int mode
)
1813 TRACE("%s: display %" B_PRIu8
", power: %s\n", __func__
, crtcID
,
1814 mode
== B_DPMS_ON
? "true" : "false");
1817 radeon_shared_info
&info
= *gInfo
->shared_info
;
1819 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args
;
1820 memset(&args
, 0, sizeof(args
));
1822 uint32 connectorIndex
= gDisplay
[crtcID
]->connectorIndex
;
1823 uint32 connectorFlags
= gConnector
[connectorIndex
]->flags
;
1824 uint16 encoderID
= gConnector
[connectorIndex
]->encoder
.objectID
;
1826 switch (encoderID
) {
1827 case ENCODER_OBJECT_ID_INTERNAL_TMDS1
:
1828 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1
:
1829 index
= GetIndexIntoMasterTable(COMMAND
, TMDSAOutputControl
);
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
);
1837 case ENCODER_OBJECT_ID_INTERNAL_DVO1
:
1838 case ENCODER_OBJECT_ID_INTERNAL_DDI
:
1839 index
= GetIndexIntoMasterTable(COMMAND
, DVOOutputControl
);
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
);
1847 index
= GetIndexIntoMasterTable(COMMAND
, DVOOutputControl
);
1849 case ENCODER_OBJECT_ID_INTERNAL_LVDS
:
1850 index
= GetIndexIntoMasterTable(COMMAND
, LCD1OutputControl
);
1852 case ENCODER_OBJECT_ID_INTERNAL_LVTM1
:
1853 if ((connectorFlags
& ATOM_DEVICE_LCD_SUPPORT
) != 0)
1854 index
= GetIndexIntoMasterTable(COMMAND
, LCD1OutputControl
);
1856 index
= GetIndexIntoMasterTable(COMMAND
, LVTMAOutputControl
);
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
);
1865 index
= GetIndexIntoMasterTable(COMMAND
, DAC1OutputControl
);
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
);
1874 index
= GetIndexIntoMasterTable(COMMAND
, DAC2OutputControl
);
1876 // default, none on purpose
1879 // If we have an index, we need to execute a table.
1883 args
.ucAction
= ATOM_ENABLE
;
1885 case B_DPMS_STAND_BY
:
1886 case B_DPMS_SUSPEND
:
1888 args
.ucAction
= ATOM_DISABLE
;
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
);
1900 if (info
.dceMajor
< 4)
1901 encoder_dpms_scratch(crtcID
, true);
1907 encoder_dpms_set_dig(uint8 crtcID
, int mode
)
1909 TRACE("%s: display %" B_PRIu8
", power: %s\n", __func__
, crtcID
,
1910 mode
== B_DPMS_ON
? "true" : "false");
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
;
1924 if ((info
.dceMajor
== 4 && info
.dceMinor
== 1)
1925 || info
.dceMajor
>= 5) {
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) {
1933 encoder_dig_setup(connectorIndex
, pll
->pixelClock
,
1934 ATOM_ENCODER_CMD_SETUP
);
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
);
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",
1948 // Enable transmitter
1949 transmitter_dig_setup(connectorIndex
, pll
->pixelClock
, 0, 0,
1950 ATOM_TRANSMITTER_ACTION_ENABLE
);
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
);
1958 dp_link_train(crtcID
);
1959 if (info
.dceMajor
>= 4) {
1960 encoder_dig_setup(connectorIndex
, pll
->pixelClock
,
1961 ATOM_ENCODER_CMD_DP_VIDEO_ON
);
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);
1967 if ((connectorFlags
& ATOM_DEVICE_LCD_SUPPORT
) != 0) {
1968 transmitter_dig_setup(connectorIndex
, pll
->pixelClock
,
1969 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON
);
1972 encoder_external_setup(connectorIndex
, ATOM_ENABLE
);
1974 case B_DPMS_STAND_BY
:
1975 case B_DPMS_SUSPEND
:
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
);
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
);
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__
);
1993 if (info
.dceMajor
>= 4) {
1994 // Disable transmitter
1995 transmitter_dig_setup(connectorIndex
, pll
->pixelClock
, 0, 0,
1996 ATOM_TRANSMITTER_ACTION_DISABLE
);
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
);
2004 if (connector_is_dp(connectorIndex
)) {
2006 ERROR("%s: TODO: dpms off set_rx_power_state D3\n",
2009 if (connector
->type
== VIDEO_CONNECTOR_EDP
) {
2010 // TODO: ATOM_TRANSMITTER_ACTION_POWER_OFF
2011 ERROR("%s: TODO, edp_panel_power!\n", __func__
);
2020 encoder_dpms_set_dvo(uint8 crtcID
, int mode
)
2022 ERROR("%s: TODO, dvo encoder dpms stub\n", __func__
);
2027 encoder_output_lock(bool lock
)
2029 TRACE("%s: %s\n", __func__
, lock
? "true" : "false");
2030 uint32 biosScratch6
= Read32(OUT
, R600_SCRATCH_REG6
);
2033 biosScratch6
|= ATOM_S6_CRITICAL_STATE
;
2034 biosScratch6
&= ~ATOM_S6_ACC_MODE
;
2036 biosScratch6
&= ~ATOM_S6_CRITICAL_STATE
;
2037 biosScratch6
|= ATOM_S6_ACC_MODE
;
2040 Write32(OUT
, R600_SCRATCH_REG6
, biosScratch6
);
2043 static const char* encoder_name_matrix
[] = {
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",
2060 "External 3rd party VT1623",
2061 "External HDMI SI1930",
2063 "Internal Kaleidoscope TMDS1",
2064 "Internal Kaleidoscope DVO1",
2065 "Internal Kaleidoscope DAC1",
2066 "Internal Kaleidoscope DAC2",
2067 "External Kaleidoscope SI178",
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"
2085 encoder_name_lookup(uint32 encoderID
) {
2086 if (encoderID
< B_COUNT_OF(encoder_name_matrix
))
2087 return encoder_name_matrix
[encoderID
];
2094 encoder_object_lookup(uint32 connectorFlags
, uint8 dacID
)
2096 // used on older cards to take a guess at the encoder
2099 radeon_shared_info
&info
= *gInfo
->shared_info
;
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
:
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
;
2117 ret
= ENCODER_INTERNAL_DAC1_ENUM_ID1
;
2120 if (info
.chipsetID
>= RADEON_RS600
)
2121 ret
= ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1
;
2123 ret
= ENCODER_INTERNAL_DAC2_ENUM_ID1
;
2126 case 3: // external dac
2127 if (info
.chipsetID
>= RADEON_RS600
)
2128 ret
= ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1
;
2130 ret
= ENCODER_INTERNAL_DVO1_ENUM_ID1
;
2134 case ATOM_DEVICE_LCD1_SUPPORT
:
2135 if (info
.chipsetID
>= RADEON_RS600
)
2136 ret
= ENCODER_INTERNAL_LVTM1_ENUM_ID1
;
2138 ret
= ENCODER_INTERNAL_LVDS_ENUM_ID1
;
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
;
2147 ret
= ENCODER_INTERNAL_TMDS1_ENUM_ID1
;
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
;
2158 ret
= ENCODER_INTERNAL_DVO1_ENUM_ID1
;
2160 case ATOM_DEVICE_DFP3_SUPPORT
:
2161 ret
= ENCODER_INTERNAL_LVTM1_ENUM_ID1
;
2170 encoder_type_lookup(uint32 encoderID
, uint32 connectorFlags
)
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
;
2180 return VIDEO_ENCODER_TMDS
;
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
;
2200 return VIDEO_ENCODER_TMDS
;
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
;
2216 return VIDEO_ENCODER_TMDS
;
2220 return VIDEO_ENCODER_NONE
;
2225 encoder_is_external(uint32 encoderID
)
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
:
2245 encoder_is_dp_bridge(uint32 encoderID
)
2247 switch (encoderID
) {
2248 case ENCODER_OBJECT_ID_TRAVIS
:
2249 case ENCODER_OBJECT_ID_NUTMEG
: