This set of patches fixes some minor things in the dce3 atom
modesetting paths and adds initial support for mode validation.  Right
now it only checks against single/dual link TMDS and against the panel
size for LVDS.  We should add support for bandwidth checking and dac
frequency as well at some point.  Patch set also contains a rebased
version of the rs880 patch I sent yesterday.

Alex
From a40ff87d19252c9ee1ea4761d0afac3d8097c869 Mon Sep 17 00:00:00 2001
From: Alex Deucher <[email protected]>
Date: Thu, 5 Nov 2009 13:11:46 -0500
Subject: [PATCH] drm/radeon/kms/r600: fix rs880 support v2

Lots of cases were wrong or missing.

v2: rebased against drm-next

Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/radeon/r600.c            |   18 ++++++++++++------
 drivers/gpu/drm/radeon/r600_blit_kms.c   |    2 +-
 drivers/gpu/drm/radeon/radeon_atombios.c |    3 ++-
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 3e5703f..35360b0 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -858,7 +858,8 @@ void r600_gpu_init(struct radeon_device *rdev)
 	    ((rdev->family) == CHIP_RV630) ||
 	    ((rdev->family) == CHIP_RV610) ||
 	    ((rdev->family) == CHIP_RV620) ||
-	    ((rdev->family) == CHIP_RS780)) {
+	    ((rdev->family) == CHIP_RS780) ||
+	    ((rdev->family) == CHIP_RS880)) {
 		WREG32(DB_DEBUG, PREZ_MUST_WAIT_FOR_POSTZ_DONE);
 	} else {
 		WREG32(DB_DEBUG, 0);
@@ -875,7 +876,8 @@ void r600_gpu_init(struct radeon_device *rdev)
 	tmp = RREG32(SQ_MS_FIFO_SIZES);
 	if (((rdev->family) == CHIP_RV610) ||
 	    ((rdev->family) == CHIP_RV620) ||
-	    ((rdev->family) == CHIP_RS780)) {
+	    ((rdev->family) == CHIP_RS780) ||
+	    ((rdev->family) == CHIP_RS880)) {
 		tmp = (CACHE_FIFO_SIZE(0xa) |
 		       FETCH_FIFO_HIWATER(0xa) |
 		       DONE_FIFO_HIWATER(0xe0) |
@@ -918,7 +920,8 @@ void r600_gpu_init(struct radeon_device *rdev)
 					    NUM_ES_STACK_ENTRIES(0));
 	} else if (((rdev->family) == CHIP_RV610) ||
 		   ((rdev->family) == CHIP_RV620) ||
-		   ((rdev->family) == CHIP_RS780)) {
+		   ((rdev->family) == CHIP_RS780) ||
+		   ((rdev->family) == CHIP_RS880)) {
 		/* no vertex cache */
 		sq_config &= ~VC_ENABLE;
 
@@ -975,7 +978,8 @@ void r600_gpu_init(struct radeon_device *rdev)
 
 	if (((rdev->family) == CHIP_RV610) ||
 	    ((rdev->family) == CHIP_RV620) ||
-	    ((rdev->family) == CHIP_RS780)) {
+	    ((rdev->family) == CHIP_RS780) ||
+	    ((rdev->family) == CHIP_RS880)) {
 		WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(TC_ONLY));
 	} else {
 		WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC));
@@ -1001,8 +1005,9 @@ void r600_gpu_init(struct radeon_device *rdev)
 	tmp = rdev->config.r600.max_pipes * 16;
 	switch (rdev->family) {
 	case CHIP_RV610:
-	case CHIP_RS780:
 	case CHIP_RV620:
+	case CHIP_RS780:
+	case CHIP_RS880:
 		tmp += 32;
 		break;
 	case CHIP_RV670:
@@ -1043,8 +1048,9 @@ void r600_gpu_init(struct radeon_device *rdev)
 
 	switch (rdev->family) {
 	case CHIP_RV610:
-	case CHIP_RS780:
 	case CHIP_RV620:
+	case CHIP_RS780:
+	case CHIP_RS880:
 		tmp = TC_L2_SIZE(8);
 		break;
 	case CHIP_RV630:
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index acae33e..dbf716e 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -368,7 +368,7 @@ set_default_state(struct radeon_device *rdev)
 	if ((rdev->family == CHIP_RV610) ||
 	    (rdev->family == CHIP_RV620) ||
 	    (rdev->family == CHIP_RS780) ||
-	    (rdev->family == CHIP_RS780) ||
+	    (rdev->family == CHIP_RS880) ||
 	    (rdev->family == CHIP_RV710))
 		sq_config = 0;
 	else
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 1c9a9c4..0507224 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -277,7 +277,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
 				ATOM_DEVICE_CV_SUPPORT)
 				continue;
 
-			if ((rdev->family == CHIP_RS780) &&
+			/* IGP chips */
+			if ((rdev->flags & RADEON_IS_IGP) &&
 			    (con_obj_id ==
 			     CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
 				uint16_t igp_offset = 0;
-- 
1.5.6.3

From 68f644ab5e35c0fc5160d1ea0da737a4fd8a2d53 Mon Sep 17 00:00:00 2001
From: Alex Deucher <[email protected]>
Date: Thu, 5 Nov 2009 01:16:23 -0500
Subject: [PATCH] drm/radeon/kms/atom/dce3: fix up usPixelClock calculation for Transmitter tables

Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/radeon/radeon_encoders.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 2aa5994..355b0fb 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -725,10 +725,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
 
 	if (ASIC_IS_DCE32(rdev)) {
 		if (radeon_encoder->pixel_clock > 165000) {
-			args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 2) / 100);
+			args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
 			args.v2.acConfig.fDualLinkConnector = 1;
 		} else {
-			args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 4) / 100);
+			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 		}
 		if (dig->dig_block)
 			args.v2.acConfig.ucEncoderSel = 1;
@@ -754,7 +754,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
 		}
 	} else {
 		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
-		args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock) / 10);
+		if (radeon_encoder->pixel_clock > 165000)
+			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+		else
+			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-- 
1.5.6.3

From f27af1255ac6215fb522f2ae75baa293f5d64993 Mon Sep 17 00:00:00 2001
From: Alex Deucher <[email protected]>
Date: Thu, 5 Nov 2009 13:16:01 -0500
Subject: [PATCH] drm/radeon/kms: store detailed connector info

This will be useful for mode validation and certain
atom tables.

Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/radeon/radeon_atombios.c   |   76 ++++++++++++-
 drivers/gpu/drm/radeon/radeon_combios.c    |  162 +++++++++++++++++++++-------
 drivers/gpu/drm/radeon/radeon_connectors.c |    8 +-
 drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
 4 files changed, 199 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 0507224..80aacde 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -46,7 +46,8 @@ radeon_add_atom_connector(struct drm_device *dev,
 			  uint32_t supported_device,
 			  int connector_type,
 			  struct radeon_i2c_bus_rec *i2c_bus,
-			  bool linkb, uint32_t igp_lane_info);
+			  bool linkb, uint32_t igp_lane_info,
+			  uint16_t connector_object_id);
 
 /* from radeon_legacy_encoder.c */
 extern void
@@ -193,6 +194,23 @@ const int supported_devices_connector_convert[] = {
 	DRM_MODE_CONNECTOR_DisplayPort
 };
 
+const uint16_t supported_devices_connector_object_id_convert[] = {
+	CONNECTOR_OBJECT_ID_NONE,
+	CONNECTOR_OBJECT_ID_VGA,
+	CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */
+	CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */
+	CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */
+	CONNECTOR_OBJECT_ID_COMPOSITE,
+	CONNECTOR_OBJECT_ID_SVIDEO,
+	CONNECTOR_OBJECT_ID_LVDS,
+	CONNECTOR_OBJECT_ID_9PIN_DIN,
+	CONNECTOR_OBJECT_ID_9PIN_DIN,
+	CONNECTOR_OBJECT_ID_DISPLAYPORT,
+	CONNECTOR_OBJECT_ID_HDMI_TYPE_A,
+	CONNECTOR_OBJECT_ID_HDMI_TYPE_B,
+	CONNECTOR_OBJECT_ID_SVIDEO
+};
+
 const int object_connector_convert[] = {
 	DRM_MODE_CONNECTOR_Unknown,
 	DRM_MODE_CONNECTOR_DVII,
@@ -229,7 +247,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
 	ATOM_OBJECT_HEADER *obj_header;
 	int i, j, path_size, device_support;
 	int connector_type;
-	uint16_t igp_lane_info, conn_id;
+	uint16_t igp_lane_info, conn_id, connector_object_id;
 	bool linkb;
 	struct radeon_i2c_bus_rec ddc_bus;
 
@@ -312,6 +330,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
 						connector_type =
 						    object_connector_convert
 						    [ct];
+						connector_object_id = ct;
 						igp_lane_info =
 						    slot_config & 0xffff;
 					} else
@@ -322,6 +341,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
 				igp_lane_info = 0;
 				connector_type =
 				    object_connector_convert[con_obj_id];
+				connector_object_id = con_obj_id;
 			}
 
 			if (connector_type == DRM_MODE_CONNECTOR_Unknown)
@@ -426,7 +446,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
 						  le16_to_cpu(path->
 							      usDeviceTag),
 						  connector_type, &ddc_bus,
-						  linkb, igp_lane_info);
+						  linkb, igp_lane_info,
+						  connector_object_id);
 
 		}
 	}
@@ -436,6 +457,45 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
 	return true;
 }
 
+static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
+						 int connector_type,
+						 uint16_t devices)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		return supported_devices_connector_object_id_convert
+			[connector_type];
+	} else if (((connector_type == DRM_MODE_CONNECTOR_DVII) ||
+		    (connector_type == DRM_MODE_CONNECTOR_DVID)) &&
+		   (devices & ATOM_DEVICE_DFP2_SUPPORT))  {
+		struct radeon_mode_info *mode_info = &rdev->mode_info;
+		struct atom_context *ctx = mode_info->atom_context;
+		int index = GetIndexIntoMasterTable(DATA, XTMDS_Info);
+		uint16_t size, data_offset;
+		uint8_t frev, crev;
+		ATOM_XTMDS_INFO *xtmds;
+
+		atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
+		xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
+
+		if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
+			if (connector_type == DRM_MODE_CONNECTOR_DVII)
+				return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
+			else
+				return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
+		} else {
+			if (connector_type == DRM_MODE_CONNECTOR_DVII)
+				return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+			else
+				return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
+		}
+	} else {
+		return supported_devices_connector_object_id_convert
+			[connector_type];
+	}
+}
+
 struct bios_connector {
 	bool valid;
 	uint16_t line_mux;
@@ -594,14 +654,20 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
 
 	/* add the connectors */
 	for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
-		if (bios_connectors[i].valid)
+		if (bios_connectors[i].valid) {
+			uint16_t connector_object_id =
+				atombios_get_connector_object_id(dev,
+						      bios_connectors[i].connector_type,
+						      bios_connectors[i].devices);
 			radeon_add_atom_connector(dev,
 						  bios_connectors[i].line_mux,
 						  bios_connectors[i].devices,
 						  bios_connectors[i].
 						  connector_type,
 						  &bios_connectors[i].ddc_bus,
-						  false, 0);
+						  false, 0,
+						  connector_object_id);
+		}
 	}
 
 	radeon_link_encoder_connector(dev);
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index a36ede0..5253cbf 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -49,7 +49,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
 			    uint32_t connector_id,
 			    uint32_t supported_device,
 			    int connector_type,
-			    struct radeon_i2c_bus_rec *i2c_bus);
+			    struct radeon_i2c_bus_rec *i2c_bus,
+			    uint16_t connector_object_id);
 
 /* from radeon_legacy_encoder.c */
 extern void
@@ -1176,7 +1177,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 			radeon_add_legacy_connector(dev, 0,
 						    ATOM_DEVICE_CRT1_SUPPORT,
 						    DRM_MODE_CONNECTOR_VGA,
-						    &ddc_i2c);
+						    &ddc_i2c,
+						    CONNECTOR_OBJECT_ID_VGA);
 		} else if (rdev->flags & RADEON_IS_MOBILITY) {
 			/* LVDS */
 			ddc_i2c = combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
@@ -1188,7 +1190,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 			radeon_add_legacy_connector(dev, 0,
 						    ATOM_DEVICE_LCD1_SUPPORT,
 						    DRM_MODE_CONNECTOR_LVDS,
-						    &ddc_i2c);
+						    &ddc_i2c,
+						    CONNECTOR_OBJECT_ID_LVDS);
 
 			/* VGA - primary dac */
 			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
@@ -1200,7 +1203,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 			radeon_add_legacy_connector(dev, 1,
 						    ATOM_DEVICE_CRT1_SUPPORT,
 						    DRM_MODE_CONNECTOR_VGA,
-						    &ddc_i2c);
+						    &ddc_i2c,
+						    CONNECTOR_OBJECT_ID_VGA);
 		} else {
 			/* DVI-I - tv dac, int tmds */
 			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
@@ -1218,7 +1222,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 						    ATOM_DEVICE_DFP1_SUPPORT |
 						    ATOM_DEVICE_CRT2_SUPPORT,
 						    DRM_MODE_CONNECTOR_DVII,
-						    &ddc_i2c);
+						    &ddc_i2c,
+						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
 
 			/* VGA - primary dac */
 			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
@@ -1230,7 +1235,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 			radeon_add_legacy_connector(dev, 1,
 						    ATOM_DEVICE_CRT1_SUPPORT,
 						    DRM_MODE_CONNECTOR_VGA,
-						    &ddc_i2c);
+						    &ddc_i2c,
+						    CONNECTOR_OBJECT_ID_VGA);
 		}
 
 		if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) {
@@ -1243,7 +1249,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 			radeon_add_legacy_connector(dev, 2,
 						    ATOM_DEVICE_TV1_SUPPORT,
 						    DRM_MODE_CONNECTOR_SVIDEO,
-						    &ddc_i2c);
+						    &ddc_i2c,
+						    CONNECTOR_OBJECT_ID_SVIDEO);
 		}
 		break;
 	case CT_IBOOK:
@@ -1257,7 +1264,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								0),
 					  ATOM_DEVICE_LCD1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
-					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_LVDS);
 		/* VGA - TV DAC */
 		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
@@ -1266,7 +1274,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								2),
 					  ATOM_DEVICE_CRT2_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
-					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_VGA);
 		/* TV - TV DAC */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
@@ -1275,7 +1284,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 					  ATOM_DEVICE_TV1_SUPPORT);
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
-					    &ddc_i2c);
+					    &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SVIDEO);
 		break;
 	case CT_POWERBOOK_EXTERNAL:
 		DRM_INFO("Connector Table: %d (powerbook external tmds)\n",
@@ -1288,7 +1298,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								0),
 					  ATOM_DEVICE_LCD1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
-					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_LVDS);
 		/* DVI-I - primary dac, ext tmds */
 		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
@@ -1301,10 +1312,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								ATOM_DEVICE_CRT1_SUPPORT,
 								1),
 					  ATOM_DEVICE_CRT1_SUPPORT);
+		/* XXX some are SL */
 		radeon_add_legacy_connector(dev, 1,
 					    ATOM_DEVICE_DFP2_SUPPORT |
 					    ATOM_DEVICE_CRT1_SUPPORT,
-					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I);
 		/* TV - TV DAC */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
@@ -1313,7 +1326,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 					  ATOM_DEVICE_TV1_SUPPORT);
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
-					    &ddc_i2c);
+					    &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SVIDEO);
 		break;
 	case CT_POWERBOOK_INTERNAL:
 		DRM_INFO("Connector Table: %d (powerbook internal tmds)\n",
@@ -1326,7 +1340,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								0),
 					  ATOM_DEVICE_LCD1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
-					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_LVDS);
 		/* DVI-I - primary dac, int tmds */
 		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
@@ -1342,7 +1357,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 		radeon_add_legacy_connector(dev, 1,
 					    ATOM_DEVICE_DFP1_SUPPORT |
 					    ATOM_DEVICE_CRT1_SUPPORT,
-					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
 		/* TV - TV DAC */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
@@ -1351,7 +1367,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 					  ATOM_DEVICE_TV1_SUPPORT);
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
-					    &ddc_i2c);
+					    &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SVIDEO);
 		break;
 	case CT_POWERBOOK_VGA:
 		DRM_INFO("Connector Table: %d (powerbook vga)\n",
@@ -1364,7 +1381,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								0),
 					  ATOM_DEVICE_LCD1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
-					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_LVDS);
 		/* VGA - primary dac */
 		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
@@ -1373,7 +1391,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								1),
 					  ATOM_DEVICE_CRT1_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT,
-					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_VGA);
 		/* TV - TV DAC */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
@@ -1382,7 +1401,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 					  ATOM_DEVICE_TV1_SUPPORT);
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
-					    &ddc_i2c);
+					    &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SVIDEO);
 		break;
 	case CT_MINI_EXTERNAL:
 		DRM_INFO("Connector Table: %d (mini external tmds)\n",
@@ -1399,10 +1419,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								ATOM_DEVICE_CRT2_SUPPORT,
 								2),
 					  ATOM_DEVICE_CRT2_SUPPORT);
+		/* XXX are any DL? */
 		radeon_add_legacy_connector(dev, 0,
 					    ATOM_DEVICE_DFP2_SUPPORT |
 					    ATOM_DEVICE_CRT2_SUPPORT,
-					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
 		/* TV - TV DAC */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
@@ -1411,7 +1433,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 					  ATOM_DEVICE_TV1_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
-					    &ddc_i2c);
+					    &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SVIDEO);
 		break;
 	case CT_MINI_INTERNAL:
 		DRM_INFO("Connector Table: %d (mini internal tmds)\n",
@@ -1431,7 +1454,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 		radeon_add_legacy_connector(dev, 0,
 					    ATOM_DEVICE_DFP1_SUPPORT |
 					    ATOM_DEVICE_CRT2_SUPPORT,
-					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
 		/* TV - TV DAC */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
@@ -1440,7 +1464,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 					  ATOM_DEVICE_TV1_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
-					    &ddc_i2c);
+					    &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SVIDEO);
 		break;
 	case CT_IMAC_G5_ISIGHT:
 		DRM_INFO("Connector Table: %d (imac g5 isight)\n",
@@ -1453,7 +1478,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								0),
 					  ATOM_DEVICE_DFP1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT,
-					    DRM_MODE_CONNECTOR_DVID, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_DVID, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
 		/* VGA - tv dac */
 		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
 		radeon_add_legacy_encoder(dev,
@@ -1462,7 +1488,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								2),
 					  ATOM_DEVICE_CRT2_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
-					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_VGA);
 		/* TV - TV DAC */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
@@ -1471,7 +1498,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 					  ATOM_DEVICE_TV1_SUPPORT);
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
-					    &ddc_i2c);
+					    &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SVIDEO);
 		break;
 	case CT_EMAC:
 		DRM_INFO("Connector Table: %d (emac)\n",
@@ -1484,7 +1512,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								1),
 					  ATOM_DEVICE_CRT1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
-					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_VGA);
 		/* VGA - tv dac */
 		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
 		radeon_add_legacy_encoder(dev,
@@ -1493,7 +1522,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 								2),
 					  ATOM_DEVICE_CRT2_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
-					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_VGA);
 		/* TV - TV DAC */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
@@ -1502,7 +1532,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 					  ATOM_DEVICE_TV1_SUPPORT);
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
-					    &ddc_i2c);
+					    &ddc_i2c,
+					    CONNECTOR_OBJECT_ID_SVIDEO);
 		break;
 	default:
 		DRM_INFO("Connector table: %d (invalid)\n",
@@ -1596,11 +1627,46 @@ static bool radeon_apply_legacy_tv_quirks(struct drm_device *dev)
 	return true;
 }
 
+static uint16_t combios_check_dl_dvi(struct drm_device *dev, int is_dvi_d)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t ext_tmds_info;
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		if (is_dvi_d)
+			return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
+		else
+			return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+	}
+	ext_tmds_info = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
+	if (ext_tmds_info) {
+		uint8_t rev = RBIOS8(ext_tmds_info);
+		uint8_t flags = RBIOS8(ext_tmds_info + 4 + 5);
+		if (rev >= 3) {
+			if (is_dvi_d)
+				return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
+			else
+				return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
+		} else {
+			if (flags & 1) {
+				if (is_dvi_d)
+					return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
+				else
+					return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
+			}
+		}
+	}
+	if (is_dvi_d)
+		return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
+	else
+		return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+}
+
 bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	uint32_t conn_info, entry, devices;
-	uint16_t tmp;
+	uint16_t tmp, connector_object_id;
 	enum radeon_combios_ddc ddc_type;
 	enum radeon_combios_connector connector;
 	int i = 0;
@@ -1660,7 +1726,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 				radeon_add_legacy_connector(dev, i, devices,
 							    legacy_connector_convert
 							    [connector],
-							    &ddc_i2c);
+							    &ddc_i2c,
+							    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
 				break;
 			case CONNECTOR_CRT_LEGACY:
 				if (tmp & 0x1) {
@@ -1685,7 +1752,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 							    devices,
 							    legacy_connector_convert
 							    [connector],
-							    &ddc_i2c);
+							    &ddc_i2c,
+							    CONNECTOR_OBJECT_ID_VGA);
 				break;
 			case CONNECTOR_DVI_I_LEGACY:
 				devices = 0;
@@ -1714,6 +1782,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 								   ATOM_DEVICE_DFP2_SUPPORT,
 								   0),
 								  ATOM_DEVICE_DFP2_SUPPORT);
+					connector_object_id = combios_check_dl_dvi(dev, 0);
 				} else {
 					devices |= ATOM_DEVICE_DFP1_SUPPORT;
 					radeon_add_legacy_encoder(dev,
@@ -1722,19 +1791,24 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 								   ATOM_DEVICE_DFP1_SUPPORT,
 								   0),
 								  ATOM_DEVICE_DFP1_SUPPORT);
+					connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
 				}
 				radeon_add_legacy_connector(dev,
 							    i,
 							    devices,
 							    legacy_connector_convert
 							    [connector],
-							    &ddc_i2c);
+							    &ddc_i2c,
+							    connector_object_id);
 				break;
 			case CONNECTOR_DVI_D_LEGACY:
-				if ((tmp >> 4) & 0x1)
+				if ((tmp >> 4) & 0x1) {
 					devices = ATOM_DEVICE_DFP2_SUPPORT;
-				else
+					connector_object_id = combios_check_dl_dvi(dev, 1);
+				} else {
 					devices = ATOM_DEVICE_DFP1_SUPPORT;
+					connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+				}
 				radeon_add_legacy_encoder(dev,
 							  radeon_get_encoder_id
 							  (dev, devices, 0),
@@ -1742,7 +1816,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 				radeon_add_legacy_connector(dev, i, devices,
 							    legacy_connector_convert
 							    [connector],
-							    &ddc_i2c);
+							    &ddc_i2c,
+							    connector_object_id);
 				break;
 			case CONNECTOR_CTV_LEGACY:
 			case CONNECTOR_STV_LEGACY:
@@ -1756,7 +1831,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 							    ATOM_DEVICE_TV1_SUPPORT,
 							    legacy_connector_convert
 							    [connector],
-							    &ddc_i2c);
+							    &ddc_i2c,
+							    CONNECTOR_OBJECT_ID_SVIDEO);
 				break;
 			default:
 				DRM_ERROR("Unknown connector type: %d\n",
@@ -1788,7 +1864,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 						    ATOM_DEVICE_CRT1_SUPPORT |
 						    ATOM_DEVICE_DFP1_SUPPORT,
 						    DRM_MODE_CONNECTOR_DVII,
-						    &ddc_i2c);
+						    &ddc_i2c,
+						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
 		} else {
 			uint16_t crt_info =
 				combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
@@ -1804,7 +1881,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 							    0,
 							    ATOM_DEVICE_CRT1_SUPPORT,
 							    DRM_MODE_CONNECTOR_VGA,
-							    &ddc_i2c);
+							    &ddc_i2c,
+							    CONNECTOR_OBJECT_ID_VGA);
 			} else {
 				DRM_DEBUG("No connector info found\n");
 				return false;
@@ -1903,7 +1981,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 						    5,
 						    ATOM_DEVICE_LCD1_SUPPORT,
 						    DRM_MODE_CONNECTOR_LVDS,
-						    &ddc_i2c);
+						    &ddc_i2c,
+						    CONNECTOR_OBJECT_ID_LVDS);
 		}
 	}
 
@@ -1923,7 +2002,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 					radeon_add_legacy_connector(dev, 6,
 								    ATOM_DEVICE_TV1_SUPPORT,
 								    DRM_MODE_CONNECTOR_SVIDEO,
-								    &ddc_i2c);
+								    &ddc_i2c,
+								    CONNECTOR_OBJECT_ID_SVIDEO);
 				}
 			}
 		}
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index ce3a785..fb4d918 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -823,7 +823,8 @@ radeon_add_atom_connector(struct drm_device *dev,
 			  int connector_type,
 			  struct radeon_i2c_bus_rec *i2c_bus,
 			  bool linkb,
-			  uint32_t igp_lane_info)
+			  uint32_t igp_lane_info,
+			  uint16_t connector_object_id)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_connector *connector;
@@ -862,6 +863,7 @@ radeon_add_atom_connector(struct drm_device *dev,
 	radeon_connector->connector_id = connector_id;
 	radeon_connector->devices = supported_device;
 	radeon_connector->shared_ddc = shared_ddc;
+	radeon_connector->connector_object_id = connector_object_id;
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -1013,7 +1015,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
 			    uint32_t connector_id,
 			    uint32_t supported_device,
 			    int connector_type,
-			    struct radeon_i2c_bus_rec *i2c_bus)
+			    struct radeon_i2c_bus_rec *i2c_bus,
+			    uint16_t connector_object_id)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_connector *connector;
@@ -1042,6 +1045,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
 
 	radeon_connector->connector_id = connector_id;
 	radeon_connector->devices = supported_device;
+	radeon_connector->connector_object_id = connector_object_id;
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index ccb7838..ace726a 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -317,6 +317,7 @@ struct radeon_connector {
 	struct edid *edid;
 	void *con_priv;
 	bool dac_load_detect;
+	uint16_t connector_object_id;
 };
 
 struct radeon_framebuffer {
-- 
1.5.6.3

From 5f37d3a7de6048523ed80fe4f3777077e8842c1d Mon Sep 17 00:00:00 2001
From: Alex Deucher <[email protected]>
Date: Thu, 5 Nov 2009 02:21:06 -0500
Subject: [PATCH] drm/radeon/kms/atom/dce3: call transmitter init on mode set

Generally this is done at post, but might not always be done
with softboot or for connectors on docking stations.

Could probably be done once when the driver loads/resumes
rather than on each mode set.

Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/radeon/radeon_encoders.c |   20 ++++++++++----------
 1 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 355b0fb..d42bc51 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -722,14 +722,17 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
 
 	args.v1.ucAction = action;
-
+	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+		args.v1.usInitInfo = radeon_connector->connector_object_id;
+	} else {
+		if (radeon_encoder->pixel_clock > 165000)
+			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+		else
+			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+	}
 	if (ASIC_IS_DCE32(rdev)) {
-		if (radeon_encoder->pixel_clock > 165000) {
+		if (radeon_encoder->pixel_clock > 165000)
 			args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
-			args.v2.acConfig.fDualLinkConnector = 1;
-		} else {
-			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-		}
 		if (dig->dig_block)
 			args.v2.acConfig.ucEncoderSel = 1;
 
@@ -754,10 +757,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
 		}
 	} else {
 		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
-		if (radeon_encoder->pixel_clock > 165000)
-			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
-		else
-			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
@@ -1140,6 +1139,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 
 		/* setup and enable the encoder and transmitter */
 		atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT);
 		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP);
 		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
 		break;
-- 
1.5.6.3

From 79653120b52e81287b22017727bf194767d158b1 Mon Sep 17 00:00:00 2001
From: Alex Deucher <[email protected]>
Date: Thu, 5 Nov 2009 11:57:07 -0500
Subject: [PATCH] drm/radeon/kms: initial mode validation support

Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   48 +++++++++++++++++++++++++++-
 1 files changed, 47 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index fb4d918..fce4c40 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -397,6 +397,30 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
 static int radeon_lvds_mode_valid(struct drm_connector *connector,
 				  struct drm_display_mode *mode)
 {
+	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+
+	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
+		return MODE_PANEL;
+
+	if (encoder) {
+		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+		struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+
+		/* AVIVO hardware supports downscaling modes larger than the panel
+		 * to the panel size, but I'm not sure this is desirable.
+		 */
+		if ((mode->hdisplay > native_mode->hdisplay) ||
+		    (mode->vdisplay > native_mode->vdisplay))
+			return MODE_PANEL;
+
+		/* if scaling is disabled, block non-native modes */
+		if (radeon_encoder->rmx_type == RMX_OFF) {
+			if ((mode->hdisplay != native_mode->hdisplay) ||
+			    (mode->vdisplay != native_mode->vdisplay))
+				return MODE_PANEL;
+		}
+	}
+
 	return MODE_OK;
 }
 
@@ -512,6 +536,8 @@ static int radeon_vga_get_modes(struct drm_connector *connector)
 static int radeon_vga_mode_valid(struct drm_connector *connector,
 				  struct drm_display_mode *mode)
 {
+	/* XXX check mode bandwidth */
+	/* XXX verify against max DAC output frequency */
 	return MODE_OK;
 }
 
@@ -609,6 +635,8 @@ static int radeon_tv_get_modes(struct drm_connector *connector)
 static int radeon_tv_mode_valid(struct drm_connector *connector,
 				struct drm_display_mode *mode)
 {
+	if ((mode->hdisplay > 1024) || (mode->vdisplay > 768))
+		return MODE_CLOCK_RANGE;
 	return MODE_OK;
 }
 
@@ -801,9 +829,27 @@ static void radeon_dvi_force(struct drm_connector *connector)
 		radeon_connector->use_digital = true;
 }
 
+static int radeon_dvi_mode_valid(struct drm_connector *connector,
+				  struct drm_display_mode *mode)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+	/* XXX check mode bandwidth */
+
+	if (radeon_connector->use_digital && (mode->clock > 165000)) {
+		if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
+		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
+		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
+			return MODE_OK;
+		else
+			return MODE_CLOCK_HIGH;
+	}
+	return MODE_OK;
+}
+
 struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
 	.get_modes = radeon_dvi_get_modes,
-	.mode_valid = radeon_vga_mode_valid,
+	.mode_valid = radeon_dvi_mode_valid,
 	.best_encoder = radeon_dvi_encoder,
 };
 
-- 
1.5.6.3

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
--
_______________________________________________
Dri-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to