diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-01-28 14:33:14 -0500 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2009-01-28 14:33:14 -0500 |
commit | bd8021d46e9066e4cd116c03a7b7adcfe2557aff (patch) | |
tree | 4c4982475b8d3acbbf943b194141ae0876043479 /src/atombios_output.c | |
parent | 4f88dd83f290fb38e41256a7f1804008c0f28139 (diff) | |
parent | 20d5dd387da555e895e2b73fb53e2b026dd91003 (diff) |
Merge branch 'atom-rework' and fix conflicts
Diffstat (limited to 'src/atombios_output.c')
-rw-r--r-- | src/atombios_output.c | 970 |
1 files changed, 516 insertions, 454 deletions
diff --git a/src/atombios_output.c b/src/atombios_output.c index 796aaed9..0827d746 100644 --- a/src/atombios_output.c +++ b/src/atombios_output.c @@ -45,23 +45,59 @@ #include "ati_pciids_gen.h" +const char *device_name[12] = { + "CRT1", + "LCD1", + "TV1", + "DFP1", + "CRT2", + "LCD2", + "TV2", + "DFP2", + "CV", + "DFP3", + "DFP4", + "DFP5", +}; + static int -atombios_output_dac1_setup(xf86OutputPtr output, DisplayModePtr mode) +atombios_output_dac_setup(xf86OutputPtr output, DisplayModePtr mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; RADEONInfoPtr info = RADEONPTR(output->scrn); + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); + radeon_tvout_ptr tvout = &radeon_output->tvout; DAC_ENCODER_CONTROL_PS_ALLOCATION disp_data; AtomBiosArgRec data; unsigned char *space; + int index, num = 0; + + if (radeon_encoder == NULL) + return ATOM_NOT_IMPLEMENTED; - disp_data.ucAction = 1; + memset(&disp_data,0, sizeof(disp_data)); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); + num = 1; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); + num = 2; + break; + } - if (radeon_output->MonType == MT_CRT) + disp_data.ucAction = ATOM_ENABLE; + + if (radeon_output->active_device & (ATOM_DEVICE_CRT_SUPPORT)) disp_data.ucDacStandard = ATOM_DAC1_PS2; - else if (radeon_output->MonType == MT_CV) + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) disp_data.ucDacStandard = ATOM_DAC1_CV; - else if (OUTPUT_IS_TV) { - switch (radeon_output->tvStd) { + else { + switch (tvout->tvStd) { case TV_STD_PAL: case TV_STD_PAL_M: case TV_STD_SCART_PAL: @@ -77,87 +113,40 @@ atombios_output_dac1_setup(xf86OutputPtr output, DisplayModePtr mode) break; } } - disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10); - data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); - data.exec.dataSpace = (void *)&space; - data.exec.pspace = &disp_data; - - if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { - ErrorF("Output DAC1 setup success\n"); - return ATOM_SUCCESS; - } - - ErrorF("Output DAC1 setup failed\n"); - return ATOM_NOT_IMPLEMENTED; - -} - -static int -atombios_output_dac2_setup(xf86OutputPtr output, DisplayModePtr mode) -{ - RADEONOutputPrivatePtr radeon_output = output->driver_private; - RADEONInfoPtr info = RADEONPTR(output->scrn); - DAC_ENCODER_CONTROL_PS_ALLOCATION disp_data; - AtomBiosArgRec data; - unsigned char *space; - - disp_data.ucAction = 1; - - if (radeon_output->MonType == MT_CRT) - disp_data.ucDacStandard = ATOM_DAC2_PS2; - else if (radeon_output->MonType == MT_CV) - disp_data.ucDacStandard = ATOM_DAC2_CV; - else if (OUTPUT_IS_TV) { - switch (radeon_output->tvStd) { - case TV_STD_NTSC: - case TV_STD_NTSC_J: - case TV_STD_PAL_60: - disp_data.ucDacStandard = ATOM_DAC2_NTSC; - break; - case TV_STD_PAL: - case TV_STD_PAL_M: - case TV_STD_SCART_PAL: - case TV_STD_SECAM: - case TV_STD_PAL_CN: - disp_data.ucDacStandard = ATOM_DAC2_PAL; - break; - default: - disp_data.ucDacStandard = ATOM_DAC2_NTSC; - break; - } - } - disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10); - data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); + data.exec.index = index; data.exec.dataSpace = (void *)&space; data.exec.pspace = &disp_data; if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { - ErrorF("Output DAC2 setup success\n"); + ErrorF("Output DAC%d setup success\n", num); return ATOM_SUCCESS; } - ErrorF("Output DAC2 setup failed\n"); + ErrorF("Output DAC%d setup failed\n", num); return ATOM_NOT_IMPLEMENTED; } static int -atombios_output_tv1_setup(xf86OutputPtr output, DisplayModePtr mode) +atombios_output_tv_setup(xf86OutputPtr output, DisplayModePtr mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; + radeon_tvout_ptr tvout = &radeon_output->tvout; RADEONInfoPtr info = RADEONPTR(output->scrn); TV_ENCODER_CONTROL_PS_ALLOCATION disp_data; AtomBiosArgRec data; unsigned char *space; - disp_data.sTVEncoder.ucAction = 1; + memset(&disp_data,0, sizeof(disp_data)); - if (radeon_output->MonType == MT_CV) + disp_data.sTVEncoder.ucAction = ATOM_ENABLE; + + if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) disp_data.sTVEncoder.ucTvStandard = ATOM_TV_CV; else { - switch (radeon_output->tvStd) { + switch (tvout->tvStd) { case TV_STD_NTSC: disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; break; @@ -194,11 +183,11 @@ atombios_output_tv1_setup(xf86OutputPtr output, DisplayModePtr mode) data.exec.pspace = &disp_data; if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { - ErrorF("Output TV1 setup success\n"); + ErrorF("Output TV setup success\n"); return ATOM_SUCCESS; } - ErrorF("Output TV1 setup failed\n"); + ErrorF("Output TV setup failed\n"); return ATOM_NOT_IMPLEMENTED; } @@ -212,12 +201,12 @@ atombios_external_tmds_setup(xf86OutputPtr output, DisplayModePtr mode) AtomBiosArgRec data; unsigned char *space; - disp_data.sXTmdsEncoder.ucEnable = 1; + memset(&disp_data,0, sizeof(disp_data)); + + disp_data.sXTmdsEncoder.ucEnable = ATOM_ENABLE; if (mode->Clock > 165000) - disp_data.sXTmdsEncoder.ucMisc = 1; - else - disp_data.sXTmdsEncoder.ucMisc = 0; + disp_data.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; if (pScrn->rgbBits == 8) disp_data.sXTmdsEncoder.ucMisc |= (1 << 1); @@ -243,13 +232,13 @@ atombios_output_ddia_setup(xf86OutputPtr output, DisplayModePtr mode) AtomBiosArgRec data; unsigned char *space; + memset(&disp_data,0, sizeof(disp_data)); + disp_data.sDVOEncoder.ucAction = ATOM_ENABLE; disp_data.sDVOEncoder.usPixelClock = cpu_to_le16(mode->Clock / 10); if (mode->Clock > 165000) disp_data.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; - else - disp_data.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = 0; data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); data.exec.dataSpace = (void *)&space; @@ -265,30 +254,47 @@ atombios_output_ddia_setup(xf86OutputPtr output, DisplayModePtr mode) } static int -atombios_output_digital_setup(xf86OutputPtr output, int device, DisplayModePtr mode) +atombios_output_digital_setup(xf86OutputPtr output, DisplayModePtr mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); LVDS_ENCODER_CONTROL_PS_ALLOCATION disp_data; LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 disp_data2; AtomBiosArgRec data; unsigned char *space; int index; int major, minor; + int lvds_misc = 0; - switch (device) { - case ATOM_DEVICE_DFP1_INDEX: - index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); - break; - case ATOM_DEVICE_LCD1_INDEX: + if (radeon_encoder == NULL) + return ATOM_NOT_IMPLEMENTED; + + if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { + radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv; + if (lvds == NULL) + return ATOM_NOT_IMPLEMENTED; + lvds_misc = lvds->lvds_misc; + } + + memset(&disp_data,0, sizeof(disp_data)); + memset(&disp_data2,0, sizeof(disp_data2)); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); break; - case ATOM_DEVICE_DFP3_INDEX: - index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); break; - default: - return ATOM_NOT_IMPLEMENTED; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); + else + index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); break; } @@ -303,15 +309,18 @@ atombios_output_digital_setup(xf86OutputPtr output, int device, DisplayModePtr m case 1: disp_data.ucMisc = 0; disp_data.ucAction = PANEL_ENCODER_ACTION_ENABLE; - if (radeon_output->type == OUTPUT_HDMI) + if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) || + (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B)) disp_data.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10); - if (device == ATOM_DEVICE_LCD1_INDEX) { - if (radeon_output->lvds_misc & (1 << 0)) + if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { + if (lvds_misc & (1 << 0)) disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL; - if (radeon_output->lvds_misc & (1 << 1)) + if (lvds_misc & (1 << 1)) disp_data.ucMisc |= (1 << 1); } else { + if (radeon_output->linkb) + disp_data.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; if (mode->Clock > 165000) disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL; if (pScrn->rgbBits == 8) @@ -329,29 +338,32 @@ atombios_output_digital_setup(xf86OutputPtr output, int device, DisplayModePtr m xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Coherent Mode enabled\n"); } } - if (radeon_output->type == OUTPUT_HDMI) + if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) || + (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B)) disp_data2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; disp_data2.usPixelClock = cpu_to_le16(mode->Clock / 10); disp_data2.ucTruncate = 0; disp_data2.ucSpatial = 0; disp_data2.ucTemporal = 0; disp_data2.ucFRC = 0; - if (device == ATOM_DEVICE_LCD1_INDEX) { - if (radeon_output->lvds_misc & (1 << 0)) + if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { + if (lvds_misc & (1 << 0)) disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL; - if (radeon_output->lvds_misc & (1 << 5)) { + if (lvds_misc & (1 << 5)) { disp_data2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; - if (radeon_output->lvds_misc & (1 << 1)) + if (lvds_misc & (1 << 1)) disp_data2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; } - if (radeon_output->lvds_misc & (1 << 6)) { + if (lvds_misc & (1 << 6)) { disp_data2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; - if (radeon_output->lvds_misc & (1 << 1)) + if (lvds_misc & (1 << 1)) disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; - if (((radeon_output->lvds_misc >> 2) & 0x3) == 2) + if (((lvds_misc >> 2) & 0x3) == 2) disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; } } else { + if (radeon_output->linkb) + disp_data2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; if (mode->Clock > 165000) disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL; } @@ -393,22 +405,88 @@ atombios_maybe_hdmi_mode(xf86OutputPtr output) #endif } +int +atombios_get_encoder_mode(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* DVI should really be atombios_maybe_hdmi_mode() as well */ + switch (radeon_output->ConnectorType) { + case CONNECTOR_DVI_I: + if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) + return ATOM_ENCODER_MODE_DVI; + else + return ATOM_ENCODER_MODE_CRT; + break; + case CONNECTOR_DVI_D: + default: + return ATOM_ENCODER_MODE_DVI; + break; + case CONNECTOR_HDMI_TYPE_A: + case CONNECTOR_HDMI_TYPE_B: + return atombios_maybe_hdmi_mode(output); + break; + case CONNECTOR_LVDS: + return ATOM_ENCODER_MODE_LVDS; + break; + case CONNECTOR_DISPLAY_PORT: + return ATOM_ENCODER_MODE_DP; + break; + case CONNECTOR_DVI_A: + case CONNECTOR_VGA: + case CONNECTOR_STV: + case CONNECTOR_CTV: + case CONNECTOR_DIN: + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) + return ATOM_ENCODER_MODE_TV; + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) + return ATOM_ENCODER_MODE_CV; + else + return ATOM_ENCODER_MODE_CRT; + break; + } + +} + static int -atombios_output_dig_encoder_setup(xf86OutputPtr output, int device, DisplayModePtr mode) +atombios_output_dig_encoder_setup(xf86OutputPtr output, DisplayModePtr mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; RADEONInfoPtr info = RADEONPTR(output->scrn); + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); DIG_ENCODER_CONTROL_PS_ALLOCATION disp_data; AtomBiosArgRec data; unsigned char *space; - int index; - int major, minor; + int index, major, minor, num = 0; - if (radeon_crtc->crtc_id) - index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); - else - index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); + if (radeon_encoder == NULL) + return ATOM_NOT_IMPLEMENTED; + + memset(&disp_data,0, sizeof(disp_data)); + + if (IS_DCE32_VARIANT) { + if (radeon_crtc->crtc_id) + index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); + else + index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); + num = radeon_crtc->crtc_id + 1; + } else { + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); + num = 1; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); + num = 2; + break; + } + } atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); @@ -416,24 +494,29 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int device, DisplayModeP disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10); if (IS_DCE32_VARIANT) { - if (radeon_output->TMDSType == TMDS_UNIPHY) + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; - if (radeon_output->TMDSType == TMDS_UNIPHY1) + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; - if (radeon_output->TMDSType == TMDS_UNIPHY2) + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; + break; + } } else { - switch (device) { - case ATOM_DEVICE_DFP1_INDEX: + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: disp_data.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1; break; - case ATOM_DEVICE_LCD1_INDEX: - case ATOM_DEVICE_DFP3_INDEX: + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: disp_data.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2; break; - default: - return ATOM_NOT_IMPLEMENTED; - break; } } @@ -441,29 +524,25 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int device, DisplayModeP disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B; disp_data.ucLaneNum = 8; } else { - disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; + if (radeon_output->linkb) + disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; + else + disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; disp_data.ucLaneNum = 4; } - if (OUTPUT_IS_DVI) - disp_data.ucEncoderMode = ATOM_ENCODER_MODE_DVI; - else if (radeon_output->type == OUTPUT_HDMI) - disp_data.ucEncoderMode = atombios_maybe_hdmi_mode(output); - else if (radeon_output->type == OUTPUT_DP) - disp_data.ucEncoderMode = ATOM_ENCODER_MODE_DP; - else if (radeon_output->type == OUTPUT_LVDS) - disp_data.ucEncoderMode = ATOM_ENCODER_MODE_LVDS; + disp_data.ucEncoderMode = atombios_get_encoder_mode(output); data.exec.index = index; data.exec.dataSpace = (void *)&space; data.exec.pspace = &disp_data; if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { - ErrorF("Output DIG%d encoder setup success\n", radeon_crtc->crtc_id + 1); + ErrorF("Output DIG%d encoder setup success\n", num); return ATOM_SUCCESS; } - ErrorF("Output DIG%d setup failed\n", radeon_crtc->crtc_id + 1); + ErrorF("Output DIG%d setup failed\n", num); return ATOM_NOT_IMPLEMENTED; } @@ -474,33 +553,36 @@ union dig_transmitter_control { }; static int -atombios_output_dig_transmitter_setup(xf86OutputPtr output, int device, DisplayModePtr mode) +atombios_output_dig_transmitter_setup(xf86OutputPtr output, DisplayModePtr mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; RADEONInfoPtr info = RADEONPTR(output->scrn); + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); union dig_transmitter_control disp_data; AtomBiosArgRec data; unsigned char *space; int index, num = 0; int major, minor; + if (radeon_encoder == NULL) + return ATOM_NOT_IMPLEMENTED; + memset(&disp_data,0, sizeof(disp_data)); + if (IS_DCE32_VARIANT) index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); else { - switch (device) { - case ATOM_DEVICE_DFP1_INDEX: + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); - num = 1; break; - case ATOM_DEVICE_LCD1_INDEX: - case ATOM_DEVICE_DFP3_INDEX: + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); - num = 2; - break; - default: - return ATOM_NOT_IMPLEMENTED; break; } } @@ -518,26 +600,23 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int device, DisplayM } if (radeon_crtc->crtc_id) disp_data.v2.acConfig.ucEncoderSel = 1; - - switch (radeon_output->TMDSType) { - case TMDS_UNIPHY: + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: disp_data.v2.acConfig.ucTransmitterSel = 0; num = 0; break; - case TMDS_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: disp_data.v2.acConfig.ucTransmitterSel = 1; num = 1; break; - case TMDS_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: disp_data.v2.acConfig.ucTransmitterSel = 2; num = 2; break; - default: - return ATOM_NOT_IMPLEMENTED; - break; } - - if (OUTPUT_IS_DVI || (radeon_output->type == OUTPUT_HDMI)) { + + if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { if (radeon_output->coherent_mode) { disp_data.v2.acConfig.fCoherentMode = 1; xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode enabled\n",disp_data.v2.acConfig.ucTransmitterSel); @@ -547,52 +626,74 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int device, DisplayM } else { disp_data.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; disp_data.v1.usPixelClock = cpu_to_le16((mode->Clock) / 10); - - if (radeon_crtc->crtc_id) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; - else + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; - - if (OUTPUT_IS_DVI || (radeon_output->type == OUTPUT_HDMI)) { + if (info->IsIGP) { + if (mode->Clock > 165000) { + disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | + ATOM_TRANSMITTER_CONFIG_LINKA_B); + /* guess */ + if (radeon_output->igp_lane_info & 0x3) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; + else if (radeon_output->igp_lane_info & 0xc) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; + } else { + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; + if (radeon_output->igp_lane_info & 0x1) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; + else if (radeon_output->igp_lane_info & 0x2) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; + else if (radeon_output->igp_lane_info & 0x4) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; + else if (radeon_output->igp_lane_info & 0x8) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; + } + } else { + if (mode->Clock > 165000) + disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | + ATOM_TRANSMITTER_CONFIG_LINKA_B | + ATOM_TRANSMITTER_CONFIG_LANE_0_7); + else { + /* XXX */ + if (radeon_output->linkb) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; + else + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; + } + } + break; + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; + if (mode->Clock > 165000) + disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | + ATOM_TRANSMITTER_CONFIG_LINKA_B | + ATOM_TRANSMITTER_CONFIG_LANE_0_7); + else { + /* XXX */ + if (radeon_output->linkb) + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; + else + disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; + } + break; + } + + if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { if (radeon_output->coherent_mode) { disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "DIG%d transmitter: Coherent Mode enabled\n", num); } else xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "DIG%d transmitter: Coherent Mode disabled\n", num); } - - if (info->IsIGP && (radeon_output->TMDSType == TMDS_UNIPHY)) { - if (mode->Clock > 165000) { - disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | - ATOM_TRANSMITTER_CONFIG_LINKA_B); - /* guess */ - if (radeon_output->igp_lane_info & 0x3) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; - else if (radeon_output->igp_lane_info & 0xc) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; - } else { - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; - if (radeon_output->igp_lane_info & 0x1) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; - else if (radeon_output->igp_lane_info & 0x2) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; - else if (radeon_output->igp_lane_info & 0x4) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; - else if (radeon_output->igp_lane_info & 0x8) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; - } - } else { - if (mode->Clock > 165000) - disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | - ATOM_TRANSMITTER_CONFIG_LINKA_B | - ATOM_TRANSMITTER_CONFIG_LANE_0_7); - else - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; - } } - radeon_output->transmitter_config = disp_data.v1.ucConfig; - + data.exec.index = index; data.exec.dataSpace = (void *)&space; data.exec.pspace = &disp_data; @@ -859,11 +960,10 @@ atombios_output_yuv_setup(xf86OutputPtr output, Bool enable) //fix up scratch reg handling temp = INREG(reg); - if ((radeon_output->MonType == MT_CTV) || - (radeon_output->MonType == MT_STV)) + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) OUTREG(reg, (ATOM_S3_TV1_ACTIVE | (radeon_crtc->crtc_id << 18))); - else if (radeon_output->MonType == MT_CV) + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) OUTREG(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); else @@ -899,6 +999,7 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode) { RADEONInfoPtr info = RADEONPTR(output->scrn); RADEONOutputPrivatePtr radeon_output = output->driver_private; + radeon_tvout_ptr tvout = &radeon_output->tvout; RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; ENABLE_SCALER_PS_ALLOCATION disp_data; AtomBiosArgRec data; @@ -908,8 +1009,8 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode) disp_data.ucScaler = radeon_crtc->crtc_id; - if (OUTPUT_IS_TV) { - switch (radeon_output->tvStd) { + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) { + switch (tvout->tvStd) { case TV_STD_NTSC: disp_data.ucTVStandard = ATOM_TV_NTSC; break; @@ -940,7 +1041,10 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode) } disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE; ErrorF("Using TV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable); - + } else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) { + disp_data.ucTVStandard = ATOM_TV_CV; + disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE; + ErrorF("Using CV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable); } else if (radeon_output->Flags & RADEON_USE_RMX) { ErrorF("Using RMX\n"); if (radeon_output->rmx_type == RMX_FULL) @@ -957,11 +1061,11 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode) data.exec.pspace = &disp_data; if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { - if (OUTPUT_IS_TV && info->ChipFamily >= CHIP_FAMILY_RV515 && info->ChipFamily <= CHIP_FAMILY_RV570) { + if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) + && info->ChipFamily >= CHIP_FAMILY_RV515 && info->ChipFamily <= CHIP_FAMILY_RV570) { ErrorF("forcing TV scaler\n"); atom_rv515_force_tv_scaler(output->scrn); } - ErrorF("scaler %d setup success\n", radeon_crtc->crtc_id); return ATOM_SUCCESS; } @@ -971,92 +1075,21 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode) } -static AtomBiosResult -atombios_display_device_control(atomBiosHandlePtr atomBIOS, int device, Bool state) -{ - DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION disp_data; - AtomBiosArgRec data; - unsigned char *space; - - disp_data.ucAction = state; - data.exec.index = device; - data.exec.dataSpace = (void *)&space; - data.exec.pspace = &disp_data; - - if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { - ErrorF("Output %d %s success\n", device, state? "enable":"disable"); - return ATOM_SUCCESS; - } - - ErrorF("Output %d %s failed\n", device, state? "enable":"disable"); - return ATOM_NOT_IMPLEMENTED; -} - -static void -atombios_device_dpms(xf86OutputPtr output, int device, int mode) -{ - RADEONOutputPrivatePtr radeon_output = output->driver_private; - RADEONInfoPtr info = RADEONPTR(output->scrn); - int index = 0; - - switch (device) { - case ATOM_DEVICE_CRT1_SUPPORT: - case ATOM_DEVICE_CRT2_SUPPORT: - if (radeon_output->DACType == DAC_PRIMARY) - index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); - else if (radeon_output->DACType == DAC_TVDAC) - index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); - break; - case ATOM_DEVICE_DFP1_SUPPORT: - index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); - break; - case ATOM_DEVICE_DFP2_SUPPORT: - index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); - break; - case ATOM_DEVICE_DFP3_SUPPORT: - index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); - break; - case ATOM_DEVICE_LCD1_SUPPORT: - index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); - break; - case ATOM_DEVICE_TV1_SUPPORT: - if (IS_DCE3_VARIANT) - index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); - else - index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); - break; - case ATOM_DEVICE_CV_SUPPORT: - if (IS_DCE3_VARIANT) - index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); - else - index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); - break; - default: - return; - } - - switch (mode) { - case DPMSModeOn: - atombios_display_device_control(info->atomBIOS, index, ATOM_ENABLE); - break; - case DPMSModeStandby: - case DPMSModeSuspend: - case DPMSModeOff: - atombios_display_device_control(info->atomBIOS, index, ATOM_DISABLE); - break; - } -} - static int -atombios_output_dig_dpms(xf86OutputPtr output, int mode, int block) +atombios_dig_dpms(xf86OutputPtr output, int mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; RADEONInfoPtr info = RADEONPTR(output->scrn); + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); DIG_TRANSMITTER_CONTROL_PS_ALLOCATION disp_data; AtomBiosArgRec data; unsigned char *space; + if (radeon_encoder == NULL) + return ATOM_NOT_IMPLEMENTED; + memset(&disp_data, 0, sizeof(disp_data)); + switch (mode) { case DPMSModeOn: disp_data.ucAction = ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT; @@ -1070,24 +1103,31 @@ atombios_output_dig_dpms(xf86OutputPtr output, int mode, int block) disp_data.ucConfig = radeon_output->transmitter_config; - if (IS_DCE32_VARIANT) { + if (IS_DCE32_VARIANT) data.exec.index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); - } else { - if (block == 1) + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: data.exec.index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); - else + break; + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: data.exec.index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); + break; + } } data.exec.dataSpace = (void *)&space; data.exec.pspace = &disp_data; if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { - ErrorF("Output DIG%d dpms success\n", block); + ErrorF("Output DIG dpms success\n"); return ATOM_SUCCESS; } - ErrorF("Output DIG%d dpms failed\n", block); + ErrorF("Output DIG dpms failed\n"); return ATOM_NOT_IMPLEMENTED; } @@ -1096,58 +1136,106 @@ void atombios_output_dpms(xf86OutputPtr output, int mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); RADEONInfoPtr info = RADEONPTR(output->scrn); + DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION disp_data; + AtomBiosArgRec data; + unsigned char *space; + int index = 0; + Bool is_dig = FALSE; - /*ErrorF("output dpms %d\n", mode);*/ + if (radeon_encoder == NULL) + return; - if (radeon_output->MonType == MT_LCD) { - if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) { - if (IS_DCE3_VARIANT) - atombios_output_dig_dpms(output, mode, 2); + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + is_dig = TRUE; + break; + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); + else + index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); + else + index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); + else + index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); + break; + } + + switch (mode) { + case DPMSModeOn: + if (is_dig) + (void)atombios_dig_dpms(output, mode); + else { + disp_data.ucAction = ATOM_ENABLE; + data.exec.index = index; + data.exec.dataSpace = (void *)&space; + data.exec.pspace = &disp_data; + + if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) + ErrorF("Output %s enable success\n", + device_name[radeon_get_device_index(radeon_output->active_device)]); else - atombios_device_dpms(output, ATOM_DEVICE_LCD1_SUPPORT, mode); + ErrorF("Output %s enable failed\n", + device_name[radeon_get_device_index(radeon_output->active_device)]); } - } else if (radeon_output->MonType == MT_DFP) { - /*ErrorF("tmds dpms\n");*/ - if (radeon_output->devices & ATOM_DEVICE_DFP1_SUPPORT) { - if (IS_DCE3_VARIANT) - atombios_output_dig_dpms(output, mode, 1); - else - atombios_device_dpms(output, ATOM_DEVICE_DFP1_SUPPORT, mode); - } else if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT) { - if (IS_DCE32_VARIANT) - atombios_output_dig_dpms(output, mode, 2); - else if (IS_DCE3_VARIANT) - return; // fixme - else - atombios_device_dpms(output, ATOM_DEVICE_DFP2_SUPPORT, mode); - } else if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT) { - if (IS_DCE3_VARIANT) - atombios_output_dig_dpms(output, mode, 0); - else - atombios_device_dpms(output, ATOM_DEVICE_DFP3_SUPPORT, mode); - } else if (radeon_output->devices & ATOM_DEVICE_DFP4_SUPPORT) { - atombios_output_dig_dpms(output, mode, 1); - } else if (radeon_output->devices & ATOM_DEVICE_DFP5_SUPPORT) { - atombios_output_dig_dpms(output, mode, 2); + radeon_encoder->use_count++; + break; + case DPMSModeStandby: + case DPMSModeSuspend: + case DPMSModeOff: + if (radeon_encoder->use_count < 2) { + if (is_dig) + (void)atombios_dig_dpms(output, mode); + else { + disp_data.ucAction = ATOM_DISABLE; + data.exec.index = index; + data.exec.dataSpace = (void *)&space; + data.exec.pspace = &disp_data; + + if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) + == ATOM_SUCCESS) + ErrorF("Output %s disable success\n", + device_name[radeon_get_device_index(radeon_output->active_device)]); + else + ErrorF("Output %s disable failed\n", + device_name[radeon_get_device_index(radeon_output->active_device)]); + } } - } else if (radeon_output->MonType == MT_CRT) { - /*ErrorF("AGD: dac dpms\n");*/ - if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) - atombios_device_dpms(output, ATOM_DEVICE_CRT1_SUPPORT, mode); - else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) - atombios_device_dpms(output, ATOM_DEVICE_CRT2_SUPPORT, mode); - } else if (radeon_output->MonType == MT_CV) { - /*ErrorF("AGD: cv dpms\n");*/ - if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) - atombios_device_dpms(output, ATOM_DEVICE_CV_SUPPORT, mode); - } else if (radeon_output->MonType == MT_STV || - radeon_output->MonType == MT_CTV) { - /*ErrorF("AGD: tv dpms\n");*/ - if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) - atombios_device_dpms(output, ATOM_DEVICE_TV1_SUPPORT, mode); + if (radeon_encoder->use_count > 0) + radeon_encoder->use_count--; + break; } - } static void @@ -1156,6 +1244,7 @@ atombios_set_output_crtc_source(xf86OutputPtr output) RADEONOutputPrivatePtr radeon_output = output->driver_private; RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; RADEONInfoPtr info = RADEONPTR(output->scrn); + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); AtomBiosArgRec data; unsigned char *space; SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_src_param; @@ -1163,6 +1252,9 @@ atombios_set_output_crtc_source(xf86OutputPtr output) int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); int major, minor; + if (radeon_encoder == NULL) + return; + memset(&crtc_src_param, 0, sizeof(crtc_src_param)); memset(&crtc_src_param2, 0, sizeof(crtc_src_param2)); atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); @@ -1176,80 +1268,64 @@ atombios_set_output_crtc_source(xf86OutputPtr output) case 1: default: crtc_src_param.ucCRTC = radeon_crtc->crtc_id; - crtc_src_param.ucDevice = 0; - if (radeon_output->MonType == MT_CRT) { - if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_CRT1_INDEX; - else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_CRT2_INDEX; - } else if (radeon_output->MonType == MT_DFP) { - if (radeon_output->devices & ATOM_DEVICE_DFP1_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_DFP1_INDEX; - else if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_DFP2_INDEX; - else if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_DFP3_INDEX; - else if (radeon_output->devices & ATOM_DEVICE_DFP4_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_DFP4_INDEX; - else if (radeon_output->devices & ATOM_DEVICE_DFP5_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_DFP5_INDEX; - } else if (radeon_output->MonType == MT_LCD) { - if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_LCD1_INDEX; - } else if (OUTPUT_IS_TV) { - if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX; - } else if (radeon_output->MonType == MT_CV) { - if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) - crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX; - } + crtc_src_param.ucDevice = radeon_get_device_index(radeon_output->active_device); data.exec.pspace = &crtc_src_param; /*ErrorF("device sourced: 0x%x\n", crtc_src_param.ucDevice);*/ break; case 2: crtc_src_param2.ucCRTC = radeon_crtc->crtc_id; - if (radeon_output->MonType == MT_CRT) { - crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_CRT; - if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) - crtc_src_param2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; - else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) - crtc_src_param2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; - } else if (radeon_output->MonType == MT_DFP) { - if (IS_DCE3_VARIANT) { - /* we route digital encoders using the CRTC ids */ + crtc_src_param2.ucEncodeMode = atombios_get_encoder_mode(output); + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + if (IS_DCE3_VARIANT) + crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; + else + crtc_src_param2.ucEncoderID = radeon_get_device_index(radeon_output->active_device); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (IS_DCE32_VARIANT) { if (radeon_crtc->crtc_id) crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; else crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; - } else { - if (radeon_output->devices & ATOM_DEVICE_DFP1_SUPPORT) - crtc_src_param2.ucEncoderID = ATOM_DEVICE_DFP1_INDEX; - else if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT) - crtc_src_param2.ucEncoderID = ATOM_DEVICE_DFP2_INDEX; - else if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT) - crtc_src_param2.ucEncoderID = ATOM_DEVICE_DFP3_INDEX; - } - if (OUTPUT_IS_DVI) - crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_DVI; - else if (radeon_output->type == OUTPUT_HDMI) - crtc_src_param2.ucEncodeMode = - atombios_maybe_hdmi_mode(output); - else if (radeon_output->type == OUTPUT_DP) - crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_DP; - } else if (radeon_output->MonType == MT_LCD) { - if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) - crtc_src_param2.ucEncoderID = ATOM_DEVICE_LCD1_INDEX; - crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS; - } else if (OUTPUT_IS_TV) { - if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) + } else + crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; + break; + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + crtc_src_param2.ucEncoderID = radeon_get_device_index(radeon_output->active_device); + break; + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + if (IS_DCE3_VARIANT) + crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; + else + crtc_src_param2.ucEncoderID = radeon_get_device_index(radeon_output->active_device); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) + crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; - crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_TV; - } else if (radeon_output->MonType == MT_CV) { - if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) + else + crtc_src_param2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) + crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; - crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_CV; + else + crtc_src_param2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; + break; } - data.exec.pspace = &crtc_src_param2; /*ErrorF("device sourced: 0x%x\n", crtc_src_param2.ucEncoderID);*/ break; @@ -1273,9 +1349,10 @@ atombios_set_output_crtc_source(xf86OutputPtr output) } static void -atombios_apply_output_quirks(xf86OutputPtr output) +atombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; RADEONInfoPtr info = RADEONPTR(output->scrn); unsigned char *RADEONMMIO = info->MMIO; @@ -1294,6 +1371,10 @@ atombios_apply_output_quirks(xf86OutputPtr output) } } } + + /* set scaler clears this on some chips */ + if (mode->Flags & V_INTERLACE) + OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN); } void @@ -1302,75 +1383,49 @@ atombios_output_mode_set(xf86OutputPtr output, DisplayModePtr adjusted_mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; - RADEONInfoPtr info = RADEONPTR(output->scrn); + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); + + if (radeon_encoder == NULL) + return; atombios_output_scaler_setup(output, mode); atombios_set_output_crtc_source(output); - if ((radeon_output->MonType == MT_CTV) || - (radeon_output->MonType == MT_STV) || - (radeon_output->MonType == MT_CV)) + if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) atombios_output_yuv_setup(output, TRUE); else atombios_output_yuv_setup(output, FALSE); - if (radeon_output->MonType == MT_CRT) { - if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT || - radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) { - if (radeon_output->DACType == DAC_PRIMARY) - atombios_output_dac1_setup(output, adjusted_mode); - else if (radeon_output->DACType == DAC_TVDAC) - atombios_output_dac2_setup(output, adjusted_mode); - } - } else if (radeon_output->MonType == MT_DFP) { - if (radeon_output->devices & ATOM_DEVICE_DFP1_SUPPORT) { - if (IS_DCE3_VARIANT) { - atombios_output_dig_encoder_setup(output, ATOM_DEVICE_DFP1_INDEX, adjusted_mode); - atombios_output_dig_transmitter_setup(output, ATOM_DEVICE_DFP1_INDEX, adjusted_mode); - } else - atombios_output_digital_setup(output, ATOM_DEVICE_DFP1_INDEX, adjusted_mode); - } else if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT) { - if (IS_DCE32_VARIANT) { - atombios_output_dig_encoder_setup(output, ATOM_DEVICE_DFP2_INDEX, adjusted_mode); - atombios_output_dig_transmitter_setup(output, ATOM_DEVICE_DFP2_INDEX, adjusted_mode); - } else { - if ((info->ChipFamily == CHIP_FAMILY_RS600) || - (info->ChipFamily == CHIP_FAMILY_RS690) || - (info->ChipFamily == CHIP_FAMILY_RS740)) - atombios_output_ddia_setup(output, adjusted_mode); - else - atombios_external_tmds_setup(output, adjusted_mode); - } - } else if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT) { - if (IS_DCE3_VARIANT) { - atombios_output_dig_encoder_setup(output, ATOM_DEVICE_DFP3_INDEX, adjusted_mode); - atombios_output_dig_transmitter_setup(output, ATOM_DEVICE_DFP3_INDEX, adjusted_mode); - } else - atombios_output_digital_setup(output, ATOM_DEVICE_DFP3_INDEX, adjusted_mode); - } else if (radeon_output->devices & ATOM_DEVICE_DFP4_SUPPORT) { - atombios_output_dig_encoder_setup(output, ATOM_DEVICE_DFP4_INDEX, adjusted_mode); - atombios_output_dig_transmitter_setup(output, ATOM_DEVICE_DFP4_INDEX, adjusted_mode); - } else if (radeon_output->devices & ATOM_DEVICE_DFP5_SUPPORT) { - atombios_output_dig_encoder_setup(output, ATOM_DEVICE_DFP5_INDEX, adjusted_mode); - atombios_output_dig_transmitter_setup(output, ATOM_DEVICE_DFP5_INDEX, adjusted_mode); - } - } else if (radeon_output->MonType == MT_LCD) { - if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) { - if (IS_DCE3_VARIANT) { - atombios_output_dig_encoder_setup(output, ATOM_DEVICE_LCD1_INDEX, adjusted_mode); - atombios_output_dig_transmitter_setup(output, ATOM_DEVICE_LCD1_INDEX, adjusted_mode); - } else - atombios_output_digital_setup(output, ATOM_DEVICE_LCD1_INDEX, adjusted_mode); - } - } else if ((radeon_output->MonType == MT_CTV) || - (radeon_output->MonType == MT_STV) || - (radeon_output->MonType == MT_CV)) { - if (radeon_output->DACType == DAC_PRIMARY) - atombios_output_dac1_setup(output, adjusted_mode); - else if (radeon_output->DACType == DAC_TVDAC) - atombios_output_dac2_setup(output, adjusted_mode); - atombios_output_tv1_setup(output, adjusted_mode); + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + atombios_output_digital_setup(output, adjusted_mode); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + atombios_output_dig_encoder_setup(output, adjusted_mode); + atombios_output_dig_transmitter_setup(output, adjusted_mode); + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + atombios_output_ddia_setup(output, adjusted_mode); + break; + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + atombios_external_tmds_setup(output, adjusted_mode); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + atombios_output_dac_setup(output, adjusted_mode); + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) + atombios_output_tv_setup(output, adjusted_mode); + break; } - atombios_apply_output_quirks(output); + atombios_apply_output_quirks(output, adjusted_mode); } static AtomBiosResult @@ -1381,44 +1436,50 @@ atom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output) DAC_LOAD_DETECTION_PS_ALLOCATION dac_data; AtomBiosArgRec data; unsigned char *space; + int major, minor; + int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); + + atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); dac_data.sDacload.ucMisc = 0; if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) { dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); - if (radeon_output->DACType == DAC_PRIMARY) + if (info->encoders[ATOM_DEVICE_CRT1_INDEX] && + (info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)) dac_data.sDacload.ucDacType = ATOM_DAC_A; - else if (radeon_output->DACType == DAC_TVDAC) + else dac_data.sDacload.ucDacType = ATOM_DAC_B; } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) { dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); - if (radeon_output->DACType == DAC_PRIMARY) + if (info->encoders[ATOM_DEVICE_CRT2_INDEX] && + (info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)) dac_data.sDacload.ucDacType = ATOM_DAC_A; - else if (radeon_output->DACType == DAC_TVDAC) + else dac_data.sDacload.ucDacType = ATOM_DAC_B; } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) { dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); - if (radeon_output->DACType == DAC_PRIMARY) + if (info->encoders[ATOM_DEVICE_CV_INDEX] && + (info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)) dac_data.sDacload.ucDacType = ATOM_DAC_A; - else if (radeon_output->DACType == DAC_TVDAC) + else dac_data.sDacload.ucDacType = ATOM_DAC_B; - if (IS_DCE3_VARIANT) - dac_data.sDacload.ucMisc = 1; + if (minor >= 3) + dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); - if (radeon_output->DACType == DAC_PRIMARY) + if (info->encoders[ATOM_DEVICE_TV1_INDEX] && + (info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)) dac_data.sDacload.ucDacType = ATOM_DAC_A; - else if (radeon_output->DACType == DAC_TVDAC) + else dac_data.sDacload.ucDacType = ATOM_DAC_B; - if (IS_DCE3_VARIANT) - dac_data.sDacload.ucMisc = 1; } else { ErrorF("invalid output device for dac detection\n"); return ATOM_NOT_IMPLEMENTED; } - data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); + data.exec.index = index; data.exec.dataSpace = (void *)&space; data.exec.pspace = &dac_data; @@ -1433,8 +1494,9 @@ atom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output) } RADEONMonitorType -atombios_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output) +atombios_dac_detect(xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONOutputPrivatePtr radeon_output = output->driver_private; @@ -1442,9 +1504,9 @@ atombios_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output) AtomBiosResult ret; uint32_t bios_0_scratch; - if (OUTPUT_IS_TV) { + if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) { - if (radeon_output->type == OUTPUT_STV) + if (radeon_output->ConnectorType == CONNECTOR_STV) return MT_STV; else return MT_CTV; |