summaryrefslogtreecommitdiff
path: root/driver/xf86-video-ati/src/radeon_output.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2012-01-25 21:33:36 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2012-01-25 21:33:36 +0000
commit46e73e726a6a3567a4bb19b06c59826b9c6767d1 (patch)
tree8df52bebcc8ecbe55a8f8be1afae536b5fb46319 /driver/xf86-video-ati/src/radeon_output.c
parentee1cf1e0a2b9e0f7070a4d1efa6b426373e8ba67 (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.c426
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;