diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2012-01-25 21:33:36 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2012-01-25 21:33:36 +0000 |
commit | 46e73e726a6a3567a4bb19b06c59826b9c6767d1 (patch) | |
tree | 8df52bebcc8ecbe55a8f8be1afae536b5fb46319 /driver/xf86-video-ati/src/radeon_output.c | |
parent | ee1cf1e0a2b9e0f7070a4d1efa6b426373e8ba67 (diff) |
Update to xf86-video-ati 6.14.3. Tested by many.
Diffstat (limited to 'driver/xf86-video-ati/src/radeon_output.c')
-rw-r--r-- | driver/xf86-video-ati/src/radeon_output.c | 426 |
1 files changed, 374 insertions, 52 deletions
diff --git a/driver/xf86-video-ati/src/radeon_output.c b/driver/xf86-video-ati/src/radeon_output.c index 06f07245d..ccde346ec 100644 --- a/driver/xf86-video-ati/src/radeon_output.c +++ b/driver/xf86-video-ati/src/radeon_output.c @@ -32,6 +32,7 @@ #include <string.h> #include <stdio.h> +#include <fcntl.h> /* X and server generic header files */ #include "xf86.h" @@ -85,7 +86,7 @@ const char *encoder_name[34] = { "INTERNAL_UNIPHY2", }; -const char *ConnectorTypeName[17] = { +const char *ConnectorTypeName[18] = { "None", "VGA", "DVI-I", @@ -102,6 +103,7 @@ const char *ConnectorTypeName[17] = { "Unsupported", "DIN", "DisplayPort", + "eDP", "Unsupported" }; @@ -118,6 +120,8 @@ static void radeon_bios_output_crtc(xf86OutputPtr output); static void radeon_bios_output_lock(xf86OutputPtr output, Bool lock); +extern void +atombios_pick_dig_encoder(xf86OutputPtr output); void RADEONPrintPortMap(ScrnInfoPtr pScrn) { @@ -153,7 +157,7 @@ void RADEONPrintPortMap(ScrnInfoPtr pScrn) if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) ErrorF(" TV1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id]); if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) - ErrorF(" CV: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id]); + ErrorF(" CV: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id]); ErrorF(" DDC reg: 0x%x\n",(unsigned int)radeon_output->ddc_i2c.mask_clk_reg); } @@ -179,6 +183,10 @@ radeon_set_active_device(xf86OutputPtr output) radeon_output->active_device = ATOM_DEVICE_DFP4_SUPPORT; else if (radeon_output->devices & ATOM_DEVICE_DFP5_SUPPORT) radeon_output->active_device = ATOM_DEVICE_DFP5_SUPPORT; + else if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) + radeon_output->active_device = ATOM_DEVICE_LCD1_SUPPORT; + else if (radeon_output->devices & ATOM_DEVICE_LCD2_SUPPORT) + radeon_output->active_device = ATOM_DEVICE_LCD2_SUPPORT; break; case MT_CRT: if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) @@ -209,6 +217,89 @@ radeon_set_active_device(xf86OutputPtr output) } } +static Bool +monitor_is_digital(xf86MonPtr MonInfo) +{ + return (MonInfo->rawData[0x14] & 0x80) != 0; +} + +static void +RADEONGetHardCodedEDIDFromFile(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + char *EDIDlist = (char *)xf86GetOptValString(info->Options, OPTION_CUSTOM_EDID); + + radeon_output->custom_edid = FALSE; + radeon_output->custom_mon = NULL; + + if (EDIDlist != NULL) { + unsigned char* edid = xnfcalloc(128, 1); + char *name = output->name; + char *outputEDID = strstr(EDIDlist, name); + + if (outputEDID != NULL) { + char *end; + char *colon; + char *command = NULL; + int fd; + + outputEDID += strlen(name) + 1; + end = strstr(outputEDID, ";"); + if (end != NULL) + *end = 0; + + colon = strstr(outputEDID, ":"); + if (colon != NULL) { + *colon = 0; + command = colon + 1; + } + + fd = open (outputEDID, O_RDONLY); + if (fd >= 0) { + read(fd, edid, 128); + close(fd); + if (edid[1] == 0xff) { + radeon_output->custom_mon = xf86InterpretEDID(output->scrn->scrnIndex, edid); + radeon_output->custom_edid = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Successfully read Custom EDID data for output %s from %s.\n", + name, outputEDID); + if (command != NULL) { + if (!strcmp(command, "digital")) { + radeon_output->custom_mon->rawData[0x14] |= 0x80; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Forcing digital output for output %s.\n", name); + } else if (!strcmp(command, "analog")) { + radeon_output->custom_mon->rawData[0x14] &= ~0x80; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Forcing analog output for output %s.\n", name); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unknown custom EDID command: '%s'.\n", + command); + } + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Custom EDID data for %s read from %s was invalid.\n", + name, outputEDID); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not read custom EDID for output %s from file %s.\n", + name, outputEDID); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not find EDID file name for output %s; using auto detection.\n", + name); + } + } +} + + static RADEONMonitorType radeon_ddc_connected(xf86OutputPtr output) { @@ -217,26 +308,32 @@ radeon_ddc_connected(xf86OutputPtr output) RADEONMonitorType MonType = MT_NONE; xf86MonPtr MonInfo = NULL; RADEONOutputPrivatePtr radeon_output = output->driver_private; - - if (radeon_output->pI2CBus) { - /* RV410 RADEON_GPIO_VGA_DDC seems to only work via hw i2c - * We may want to extend this to other cases if the need arises... - */ - if ((info->ChipFamily == CHIP_FAMILY_RV410) && - (radeon_output->ddc_i2c.mask_clk_reg == RADEON_GPIO_VGA_DDC) && - info->IsAtomBios) - MonInfo = radeon_atom_get_edid(output); - else if (info->get_hardcoded_edid_from_bios) { - MonInfo = RADEONGetHardCodedEDIDFromBIOS(output); - if (MonInfo == NULL) { - RADEONI2CDoLock(output, TRUE); + int ret; + + if (radeon_output->custom_edid) { + MonInfo = xnfcalloc(sizeof(xf86Monitor), 1); + *MonInfo = *radeon_output->custom_mon; + } else if ((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) || + (radeon_output->ConnectorType == CONNECTOR_EDP)) { + ret = RADEON_DP_GetSinkType(output); + if (ret == CONNECTOR_OBJECT_ID_DISPLAYPORT || + ret == CONNECTOR_OBJECT_ID_eDP) { + MonInfo = xf86OutputGetEDID(output, radeon_output->dp_pI2CBus); + } + if (MonInfo == NULL) { + if (radeon_output->pI2CBus) { + RADEONI2CDoLock(output, radeon_output->pI2CBus, TRUE); MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus); - RADEONI2CDoLock(output, FALSE); + RADEONI2CDoLock(output, radeon_output->pI2CBus, FALSE); } - } else { - RADEONI2CDoLock(output, TRUE); + } + } else if (radeon_output->pI2CBus) { + if (info->get_hardcoded_edid_from_bios) + MonInfo = RADEONGetHardCodedEDIDFromBIOS(output); + if (MonInfo == NULL) { + RADEONI2CDoLock(output, radeon_output->pI2CBus, TRUE); MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus); - RADEONI2CDoLock(output, FALSE); + RADEONI2CDoLock(output, radeon_output->pI2CBus, FALSE); } } if (MonInfo) { @@ -246,23 +343,62 @@ radeon_ddc_connected(xf86OutputPtr output) break; case CONNECTOR_DVI_D: case CONNECTOR_HDMI_TYPE_A: - case CONNECTOR_HDMI_TYPE_B: if (radeon_output->shared_ddc) { - if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI/HDMI/etc. */ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (output->scrn); + int i; + + if (monitor_is_digital(MonInfo)) MonType = MT_DFP; else MonType = MT_NONE; + + for (i = 0; i < config->num_output; i++) { + if (output != config->output[i]) { + RADEONOutputPrivatePtr other_radeon_output = + config->output[i]->driver_private; + if (radeon_output->devices & other_radeon_output->devices) { +#ifndef EDID_COMPLETE_RAWDATA + if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) { + MonType = MT_NONE; + break; + } +#else + if (xf86MonitorIsHDMI(MonInfo)) { + if (radeon_output->ConnectorType == CONNECTOR_DVI_D) { + MonType = MT_NONE; + break; + } + } else { + if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) { + MonType = MT_NONE; + break; + } + } +#endif + } + } + } } else MonType = MT_DFP; break; case CONNECTOR_DISPLAY_PORT: + case CONNECTOR_EDP: /* * XXX wrong. need to infer based on whether we got DDC from I2C * or AUXCH. */ - MonType = MT_DFP; + ret = RADEON_DP_GetSinkType(output); + + if ((ret == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (ret == CONNECTOR_OBJECT_ID_eDP)) { + MonType = MT_DP; + RADEON_DP_GetDPCD(output); + } else + MonType = MT_DFP; + break; + case CONNECTOR_HDMI_TYPE_B: case CONNECTOR_DVI_I: - if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI */ + if (monitor_is_digital(MonInfo)) MonType = MT_DFP; else MonType = MT_CRT; @@ -271,7 +407,7 @@ radeon_ddc_connected(xf86OutputPtr output) case CONNECTOR_DVI_A: default: if (radeon_output->shared_ddc) { - if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and VGA */ + if (monitor_is_digital(MonInfo)) MonType = MT_NONE; else MonType = MT_CRT; @@ -280,15 +416,14 @@ radeon_ddc_connected(xf86OutputPtr output) break; } - if (MonType != MT_NONE) + if (MonType != MT_NONE) { if (!xf86ReturnOptValBool(info->Options, OPTION_IGNORE_EDID, FALSE)) xf86OutputSetEDID(output, MonInfo); + } else + free(MonInfo); } else MonType = MT_NONE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Output: %s, Detected Monitor Type: %d\n", output->name, MonType); - return MonType; } @@ -347,6 +482,22 @@ radeon_dpms(xf86OutputPtr output, int mode) if ((mode == DPMSModeOn) && radeon_output->enabled) return; + if ((mode != DPMSModeOn) && radeon_output->shared_ddc) { + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (output->scrn); + int i; + + for (i = 0; i < config->num_output; i++) { + if (output != config->output[i]) { + RADEONOutputPrivatePtr other_radeon_output = + config->output[i]->driver_private; + if (radeon_output->devices & other_radeon_output->devices) { + if (output->status == XF86OutputStatusDisconnected) + return; + } + } + } + } + if (IS_AVIVO_VARIANT || info->r4xx_atom) { atombios_output_dpms(output, mode); } else { @@ -404,12 +555,21 @@ radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) } } + /* clocks over 135 MHz have heat issues with DVI on RV100 */ + if ((radeon_output->MonType == MT_DFP) && + (info->ChipFamily == CHIP_FAMILY_RV100) && + (pMode->Clock > 135000)) + return MODE_CLOCK_HIGH; + /* single link DVI check */ if (pMode->Clock > 165000 && radeon_output->MonType == MT_DFP) { /* DP->DVI converter */ if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) return MODE_CLOCK_HIGH; + if (radeon_output->ConnectorType == CONNECTOR_EDP) + return MODE_CLOCK_HIGH; + /* XXX some HDMI can do better than 165MHz on a link */ if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) return MODE_CLOCK_HIGH; @@ -442,8 +602,11 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, RADEONInfoPtr info = RADEONPTR(output->scrn); RADEONOutputPrivatePtr radeon_output = output->driver_private; radeon_native_mode_ptr native_mode = &radeon_output->native_mode; + xf86CrtcPtr crtc = output->crtc; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; radeon_output->Flags &= ~RADEON_USE_RMX; + radeon_crtc->scaler_enabled = FALSE; /* * Refresh the Crtc values without INTERLACE_HALVE_V @@ -454,14 +617,15 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, /* decide if we are using RMX */ if ((radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) && radeon_output->rmx_type != RMX_OFF) { - xf86CrtcPtr crtc = output->crtc; - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; if (IS_AVIVO_VARIANT || radeon_crtc->crtc_id == 0) { if (mode->HDisplay < native_mode->PanelXRes || mode->VDisplay < native_mode->PanelYRes) { radeon_output->Flags |= RADEON_USE_RMX; + radeon_crtc->scaler_enabled = TRUE; if (IS_AVIVO_VARIANT) { + radeon_crtc->hsc = (float)mode->HDisplay / (float)native_mode->PanelXRes; + radeon_crtc->vsc = (float)mode->VDisplay / (float)native_mode->PanelYRes; /* set to the panel's native mode */ adjusted_mode->HDisplay = native_mode->PanelXRes; adjusted_mode->VDisplay = native_mode->PanelYRes; @@ -507,6 +671,13 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, } } + /* FIXME: vsc/hsc */ + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) { + radeon_crtc->scaler_enabled = TRUE; + radeon_crtc->hsc = (float)mode->HDisplay / (float)640; + radeon_crtc->vsc = (float)mode->VDisplay / (float)480; + } + if (IS_AVIVO_VARIANT) { /* hw bug */ if ((mode->Flags & V_INTERLACE) @@ -514,14 +685,62 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + 2; } + if (IS_AVIVO_VARIANT || info->r4xx_atom) { + if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { + radeon_tvout_ptr tvout = &radeon_output->tvout; + ScrnInfoPtr pScrn = output->scrn; + + if (tvout->tvStd == TV_STD_NTSC || + tvout->tvStd == TV_STD_NTSC_J || + tvout->tvStd == TV_STD_PAL_M) + RADEONATOMGetTVTimings(pScrn, 0, adjusted_mode); + else + RADEONATOMGetTVTimings(pScrn, 1, adjusted_mode); + } + } + + if (((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) || + (radeon_output->ConnectorType == CONNECTOR_EDP)) && + (radeon_output->MonType == MT_DP)) { + radeon_dp_mode_fixup(output, mode, adjusted_mode); + } return TRUE; } static void radeon_mode_prepare(xf86OutputPtr output) { + RADEONInfoPtr info = RADEONPTR(output->scrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (output->scrn); + int o; + + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr loop_output = config->output[o]; + if (loop_output == output) + continue; + else if (loop_output->crtc) { + xf86CrtcPtr other_crtc = loop_output->crtc; + RADEONCrtcPrivatePtr other_radeon_crtc = other_crtc->driver_private; + if (other_crtc->enabled) { + if (other_radeon_crtc->initialized) { + radeon_crtc_dpms(other_crtc, DPMSModeOff); + if (IS_AVIVO_VARIANT || info->r4xx_atom) + atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 1); + radeon_dpms(loop_output, DPMSModeOff); + } + } + } + } + radeon_bios_output_lock(output, TRUE); + if (IS_AVIVO_VARIANT) + atombios_pick_dig_encoder(output); radeon_dpms(output, DPMSModeOff); + radeon_crtc_dpms(output->crtc, DPMSModeOff); + + if (IS_AVIVO_VARIANT || info->r4xx_atom) + atombios_set_output_crtc_source(output); + } static void @@ -541,7 +760,30 @@ radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, static void radeon_mode_commit(xf86OutputPtr output) { + RADEONInfoPtr info = RADEONPTR(output->scrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (output->scrn); + int o; + + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr loop_output = config->output[o]; + if (loop_output == output) + continue; + else if (loop_output->crtc) { + xf86CrtcPtr other_crtc = loop_output->crtc; + RADEONCrtcPrivatePtr other_radeon_crtc = other_crtc->driver_private; + if (other_crtc->enabled) { + if (other_radeon_crtc->initialized) { + radeon_crtc_dpms(other_crtc, DPMSModeOn); + if (IS_AVIVO_VARIANT || info->r4xx_atom) + atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 0); + radeon_dpms(loop_output, DPMSModeOn); + } + } + } + } + radeon_dpms(output, DPMSModeOn); + radeon_crtc_dpms(output->crtc, DPMSModeOn); radeon_bios_output_lock(output, FALSE); } @@ -691,6 +933,10 @@ radeon_bios_output_crtc(xf86OutputPtr output) xf86CrtcPtr crtc = output->crtc; RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + /* no need to update crtc routing scratch regs on DCE4 */ + if (IS_DCE4_VARIANT) + return; + if (info->IsAtomBios) { if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) { save->bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE; @@ -960,6 +1206,8 @@ radeon_detect(xf86OutputPtr output) } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Output: %s, Detected Monitor Type: %d\n", output->name, radeon_output->MonType); if (output->MonInfo) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on output: %s ----------------------\n", output->name); @@ -1023,6 +1271,7 @@ radeon_detect(xf86OutputPtr output) radeon_output->MonType = MT_CV; break; case CONNECTOR_DISPLAY_PORT: + case CONNECTOR_EDP: radeon_output->MonType = MT_DP; break; } @@ -1053,7 +1302,7 @@ static void radeon_destroy (xf86OutputPtr output) { if (output->driver_private) - xfree(output->driver_private); + free(output->driver_private); } static void @@ -1174,7 +1423,7 @@ radeon_create_resources(xf86OutputPtr output) } } - if ((!IS_AVIVO_VARIANT) && (radeon_output->devices & (ATOM_DEVICE_DFP2_SUPPORT))) { + if ((!IS_AVIVO_VARIANT) && (radeon_output->devices & (ATOM_DEVICE_DFP1_SUPPORT))) { tmds_pll_atom = MAKE_ATOM("tmds_pll"); err = RRConfigureOutputProperty(output->randr_output, tmds_pll_atom, @@ -1373,10 +1622,25 @@ radeon_set_mode_for_property(xf86OutputPtr output) xf86CrtcPtr crtc = output->crtc; if (crtc->enabled) { +#ifdef RANDR_14_INTERFACE + xf86CrtcSetRec crtc_set_rec; + + crtc_set_rec.flags = (XF86CrtcSetMode | + XF86CrtcSetOutput | + XF86CrtcSetOrigin | + XF86CrtcSetRotation); + crtc_set_rec.mode = &crtc->desiredMode; + crtc_set_rec.rotation = crtc->desiredRotation; + crtc_set_rec.transform = NULL; + crtc_set_rec.x = crtc->desiredX; + crtc_set_rec.y = crtc->desiredY; + if (!xf86CrtcSet(crtc, &crtc_set_rec)) { +#else if (!xf86CrtcSetMode(crtc, &crtc->desiredMode, crtc->desiredRotation, crtc->desiredX, crtc->desiredY)) { +#endif xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to set mode after propery change!\n"); + "Failed to set mode after property change!\n"); return FALSE; } } @@ -1608,16 +1872,35 @@ static const xf86OutputFuncsRec radeon_output_funcs = { }; Bool -RADEONI2CDoLock(xf86OutputPtr output, int lock_state) +RADEONI2CDoLock(xf86OutputPtr output, I2CBusPtr b, int lock_state) { ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - RADEONI2CBusPtr pRADEONI2CBus = radeon_output->pI2CBus->DriverPrivate.ptr; + RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr; unsigned char *RADEONMMIO = info->MMIO; uint32_t temp; if (lock_state) { + /* RV410 appears to have a bug where the hw i2c in reset + * holds the i2c port in a bad state - switch hw i2c away before + * doing DDC - do this for all r200s/r300s for safety sakes */ + if ((info->ChipFamily >= CHIP_FAMILY_R200) && (!IS_AVIVO_VARIANT)) { + if (pRADEONI2CBus->mask_clk_reg == RADEON_GPIO_MONID) + OUTREG(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | + R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1))); + else + OUTREG(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | + R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3))); + } + + /* set the pad in ddc mode */ + if (IS_DCE3_VARIANT && + pRADEONI2CBus->hw_capable) { + temp = INREG(pRADEONI2CBus->mask_clk_reg); + temp &= ~(1 << 16); + OUTREG(pRADEONI2CBus->mask_clk_reg, temp); + } + temp = INREG(pRADEONI2CBus->a_clk_reg); temp &= ~(pRADEONI2CBus->a_clk_mask); OUTREG(pRADEONI2CBus->a_clk_reg, temp); @@ -1847,10 +2130,6 @@ void RADEONInitConnector(xf86OutputPtr output) else radeon_output->rmx_type = RMX_OFF; - /* dce 3.2 chips have problems with low dot clocks, so use the scaler */ - if (IS_DCE32_VARIANT && (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))) - radeon_output->rmx_type = RMX_FULL; - if (!IS_AVIVO_VARIANT) { if (radeon_output->devices & (ATOM_DEVICE_CRT2_SUPPORT)) { if (xf86ReturnOptValBool(info->Options, OPTION_TVDAC_LOAD_DETECT, FALSE)) @@ -1864,6 +2143,20 @@ void RADEONInitConnector(xf86OutputPtr output) if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT)) radeon_output->coherent_mode = TRUE; + if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) { + strcpy(radeon_output->dp_bus_name, output->name); + strcat(radeon_output->dp_bus_name, "-DP"); + RADEON_DP_I2CInit(pScrn, &radeon_output->dp_pI2CBus, radeon_output->dp_bus_name, output); + RADEON_DP_GetSinkType(output); + } + + if (radeon_output->ConnectorType == CONNECTOR_EDP) { + strcpy(radeon_output->dp_bus_name, output->name); + strcat(radeon_output->dp_bus_name, "-eDP"); + RADEON_DP_I2CInit(pScrn, &radeon_output->dp_pI2CBus, radeon_output->dp_bus_name, output); + RADEON_DP_GetSinkType(output); + } + if (radeon_output->ddc_i2c.valid) RADEONI2CInit(pScrn, &radeon_output->pI2CBus, output->name, &radeon_output->ddc_i2c); @@ -2468,7 +2761,7 @@ static RADEONMacModel RADEONDetectMacModel(ScrnInfoPtr pScrn) ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual or single link */ } - if (strcmp(model, "PowerBook5,7") == 0 || + if (strcmp(model, "PowerBook5,7") || strcmp(model, "PowerBook5,8") == 0 || strcmp(model, "PowerBook5,9") == 0) { ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual link */ @@ -2546,17 +2839,26 @@ radeon_output_clones (ScrnInfoPtr pScrn, xf86OutputPtr output) int o; int index_mask = 0; + /* no cloning with zaphod */ + if (info->IsPrimary || info->IsSecondary) + return index_mask; + /* DIG routing gets problematic */ - if (IS_DCE32_VARIANT) + if (info->ChipFamily >= CHIP_FAMILY_R600) return index_mask; /* LVDS is too wacky */ if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) return index_mask; + /* TV requires very specific timing */ if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT)) return index_mask; + /* DVO requires 2x ppll clocks depending on the tmds chip */ + if (radeon_output->devices & (ATOM_DEVICE_DFP2_SUPPORT)) + return index_mask; + for (o = 0; o < config->num_output; o++) { xf86OutputPtr clone = config->output[o]; RADEONOutputPrivatePtr radeon_clone = clone->driver_private; @@ -2595,6 +2897,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) int num_dvi = 0; int num_hdmi = 0; int num_dp = 0; + int num_edp = 0; /* We first get the information about all connectors from BIOS. * This is how the card is phyiscally wired up. @@ -2734,15 +3037,17 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) RADEONConnectorType conntype = info->BiosConnector[i].ConnectorType; if ((conntype == CONNECTOR_DVI_D) || (conntype == CONNECTOR_DVI_I) || - (conntype == CONNECTOR_DVI_A)) { + (conntype == CONNECTOR_DVI_A) || + (conntype == CONNECTOR_HDMI_TYPE_B)) { num_dvi++; } else if (conntype == CONNECTOR_VGA) { num_vga++; - } else if ((conntype == CONNECTOR_HDMI_TYPE_A) || - (conntype == CONNECTOR_HDMI_TYPE_B)) { + } else if (conntype == CONNECTOR_HDMI_TYPE_A) { num_hdmi++; } else if (conntype == CONNECTOR_DISPLAY_PORT) { num_dp++; + } else if (conntype == CONNECTOR_EDP) { + num_edp++; } } } @@ -2767,19 +3072,29 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) radeon_output->shared_ddc = info->BiosConnector[i].shared_ddc; radeon_output->load_detection = info->BiosConnector[i].load_detection; radeon_output->linkb = info->BiosConnector[i].linkb; + radeon_output->dig_encoder = -1; radeon_output->connector_id = info->BiosConnector[i].connector_object; + radeon_output->connector_object_id = info->BiosConnector[i].connector_object_id; + radeon_output->ucI2cId = info->BiosConnector[i].ucI2cId; + radeon_output->hpd_id = info->BiosConnector[i].hpd_id; + /* Technically HDMI-B is a glorfied DL DVI so the bios is correct, + * but this can be confusing to users when it comes to output names, + * so call it DVI + */ if ((conntype == CONNECTOR_DVI_D) || (conntype == CONNECTOR_DVI_I) || - (conntype == CONNECTOR_DVI_A)) { + (conntype == CONNECTOR_DVI_A) || + (conntype == CONNECTOR_HDMI_TYPE_B)) { output = RADEONOutputCreate(pScrn, "DVI-%d", --num_dvi); } else if (conntype == CONNECTOR_VGA) { output = RADEONOutputCreate(pScrn, "VGA-%d", --num_vga); - } else if ((conntype == CONNECTOR_HDMI_TYPE_A) || - (conntype == CONNECTOR_HDMI_TYPE_B)) { + } else if (conntype == CONNECTOR_HDMI_TYPE_A) { output = RADEONOutputCreate(pScrn, "HDMI-%d", --num_hdmi); } else if (conntype == CONNECTOR_DISPLAY_PORT) { output = RADEONOutputCreate(pScrn, "DisplayPort-%d", --num_dp); + } else if (conntype == CONNECTOR_EDP) { + output = RADEONOutputCreate(pScrn, "eDP-%d", --num_edp); } else { output = RADEONOutputCreate(pScrn, ConnectorTypeName[conntype], 0); @@ -2788,11 +3103,17 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) if (!output) { return FALSE; } + output->interlaceAllowed = TRUE; + output->doubleScanAllowed = TRUE; output->driver_private = radeon_output; - output->possible_crtcs = 1; - /* crtc2 can drive LVDS, it just doesn't have RMX */ - if (!(radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))) - output->possible_crtcs |= 2; + if (IS_DCE4_VARIANT) { + output->possible_crtcs = 0x3f; + } else { + output->possible_crtcs = 1; + /* crtc2 can drive LVDS, it just doesn't have RMX */ + if (!(radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))) + output->possible_crtcs |= 2; + } /* we can clone the DACs, and probably TV-out, but I'm not sure it's worth the trouble */ @@ -2806,6 +3127,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) xf86OutputPtr output = xf86_config->output[i]; output->possible_clones = radeon_output_clones(pScrn, output); + RADEONGetHardCodedEDIDFromFile(output); } return TRUE; |