diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index da6ad0d6a8..7d8934d93b 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -342,6 +342,9 @@ radeon_set_display_mode(display_mode *mode) // Power up the output PLLPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); DACPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); + } else if ((gDisplay[display_id]->connection_type & CONNECTION_TMDS) != 0) { + TMDSSet(gDisplay[display_id]->connection_id, mode); + TMDSPower(gDisplay[display_id]->connection_id, RHD_POWER_ON); } // Ensure screen isn't blanked diff --git a/src/add-ons/accelerants/radeon_hd/tmds.cpp b/src/add-ons/accelerants/radeon_hd/tmds.cpp index 09717a8485..2ecda5077f 100644 --- a/src/add-ons/accelerants/radeon_hd/tmds.cpp +++ b/src/add-ons/accelerants/radeon_hd/tmds.cpp @@ -22,6 +22,83 @@ extern "C" void _sPrintf(const char *format, ...); #endif +/* + * From Xorg Driver + * This information is not provided in an atombios data table. + */ +static struct R5xxTMDSAMacro { + uint16 device; + uint32 macro; +} R5xxTMDSAMacro[] = { + { 0x7104, 0x00C00414 }, /* R520 */ + { 0x7142, 0x00A00415 }, /* RV515 */ + { 0x7145, 0x00A00416 }, /* M54 */ + { 0x7146, 0x00C0041F }, /* RV515 */ + { 0x7147, 0x00C00418 }, /* RV505 */ + { 0x7149, 0x00800416 }, /* M56 */ + { 0x7152, 0x00A00415 }, /* RV515 */ + { 0x7183, 0x00600412 }, /* RV530 */ + { 0x71C1, 0x00C0041F }, /* RV535 */ + { 0x71C2, 0x00A00416 }, /* RV530 */ + { 0x71C4, 0x00A00416 }, /* M56 */ + { 0x71C5, 0x00A00416 }, /* M56 */ + { 0x71C6, 0x00A00513 }, /* RV530 */ + { 0x71D2, 0x00A00513 }, /* RV530 */ + { 0x71D5, 0x00A00513 }, /* M66 */ + { 0x7249, 0x00A00513 }, /* R580 */ + { 0x724B, 0x00A00513 }, /* R580 */ + { 0x7280, 0x00C0041F }, /* RV570 */ + { 0x7288, 0x00C0041F }, /* RV570 */ + { 0x9400, 0x00910419 }, /* R600: */ + { 0, 0} /* End marker */ +}; + +static struct Rv6xxTMDSAMacro { + uint16 device; + uint32 pll; + uint32 tx; +} Rv6xxTMDSAMacro[] = { + { 0x94C1, 0x00010416, 0x00010308 }, /* RV610 */ + { 0x94C3, 0x00010416, 0x00010308 }, /* RV610 */ + { 0x9501, 0x00010416, 0x00010308 }, /* RV670: != atombios */ + { 0x9505, 0x00010416, 0x00010308 }, /* RV670: != atombios */ + { 0x950F, 0x00010416, 0x00010308 }, /* R680 : != atombios */ + { 0x9581, 0x00030410, 0x00301044 }, /* M76 */ + { 0x9587, 0x00010416, 0x00010308 }, /* RV630 */ + { 0x9588, 0x00010416, 0x00010388 }, /* RV630 */ + { 0x9589, 0x00010416, 0x00010388 }, /* RV630 */ + { 0, 0, 0} /* End marker */ +}; + + +void +TMDSVoltageControl(uint8 tmdsIndex) +{ + int i; + + radeon_shared_info &info = *gInfo->shared_info; + + if (info.device_chipset < (RADEON_R600 | 0x10)) { + for (i = 0; R5xxTMDSAMacro[i].device; i++) { + if (R5xxTMDSAMacro[i].device == info.device_id) { + Write32(OUT, TMDSA_MACRO_CONTROL, R5xxTMDSAMacro[i].macro); + return; + } + } + TRACE("%s : unhandled chipset 0x%X\n", __func__, info.device_id); + } else { + for (i = 0; Rv6xxTMDSAMacro[i].device; i++) { + if (Rv6xxTMDSAMacro[i].device == info.device_id) { + Write32(OUT, TMDSA_PLL_ADJUST, Rv6xxTMDSAMacro[i].pll); + Write32(OUT, TMDSA_TRANSMITTER_ADJUST, Rv6xxTMDSAMacro[i].tx); + return; + } + } + TRACE("%s : unhandled chipset 0x%X\n", __func__, info.device_id); + } +} + + bool TMDSSense(uint8 tmdsIndex) { @@ -44,3 +121,106 @@ TMDSSense(uint8 tmdsIndex) } +status_t +TMDSPower(uint8 tmdsIndex, int command) +{ + // For now radeon cards only have TMDSA and no TMDSB + switch (command) { + case RHD_POWER_ON: + { + TRACE("%s: TMDS %d Power On\n", __func__, tmdsIndex); + Write32Mask(OUT, TMDSA_CNTL, 0x1, 0x00000001); + Write32Mask(OUT, TMDSA_TRANSMITTER_CONTROL, 0x00000001, 0x00000001); + snooze(20); + + // Reset transmitter + Write32Mask(OUT, TMDSA_TRANSMITTER_CONTROL, 0x00000002, 0x00000002); + snooze(2); + Write32Mask(OUT, TMDSA_TRANSMITTER_CONTROL, 0, 0x00000002); + + snooze(30); + + // Restart data sync + // TODO : 165000 this is DualLink + Write32Mask(OUT, TMDSA_CNTL, 0, 0x01000000); + + // Disable force data + Write32Mask(OUT, TMDSA_FORCE_OUTPUT_CNTL, 0, 0x00000001); + + // Enable DC balancer + Write32Mask(OUT, TMDSA_DCBALANCER_CONTROL, 0x00000001, 0x00000001); + + TMDSVoltageControl(tmdsIndex); + + // USE IDCLK + Write32Mask(OUT, TMDSA_TRANSMITTER_CONTROL, 0x00000010, 0x00000010); + + // TODO : if coherent? For now lets asume false + Write32Mask(OUT, TMDSA_TRANSMITTER_CONTROL, 0x10000000, 0x10000000); + + // TODO : HdmiSetMode(mode) + return B_OK; +} diff --git a/src/add-ons/accelerants/radeon_hd/tmds.h b/src/add-ons/accelerants/radeon_hd/tmds.h index 37a9b21408..3d1f750227 100644 --- a/src/add-ons/accelerants/radeon_hd/tmds.h +++ b/src/add-ons/accelerants/radeon_hd/tmds.h @@ -9,7 +9,10 @@ #define RADEON_HD_TMDS_H +void TMDSVoltageControl(uint8 tmdsIndex); bool TMDSSense(uint8 tmdsIndex); +status_t TMDSPower(uint8 tmdsIndex, int command); +status_t TMDSSet(uint8 tmdsIndex, display_mode *mode); #endif