Browse Source

drm/nouveau/bios: simplify U/d table hash matching func to just match

The caller is now responsible for parsing its own lists (or whatever) of
possible encoders.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Ben Skeggs 14 years ago
parent
commit
721b0821ad
2 changed files with 40 additions and 51 deletions
  1. 39 51
      drivers/gpu/drm/nouveau/nouveau_bios.c
  2. 1 0
      drivers/gpu/drm/nouveau/nouveau_drv.h

+ 39 - 51
drivers/gpu/drm/nouveau/nouveau_bios.c

@@ -4426,55 +4426,32 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
 	return 0;
 }
 
-static uint8_t *
-bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
-			 uint16_t record, int record_len, int record_nr,
-			 bool match_link)
+/* BIT 'U'/'d' table encoder subtables have hashes matching them to
+ * a particular set of encoders.
+ *
+ * This function returns true if a particular DCB entry matches.
+ */
+bool
+bios_encoder_match(struct dcb_entry *dcb, u32 hash)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->vbios;
-	uint32_t entry;
-	uint16_t table;
-	int i, v;
+	if ((hash & 0x000000f0) != (dcb->location << 4))
+		return false;
+	if ((hash & 0x0000000f) != dcb->type)
+		return false;
+	if (!(hash & (dcb->or << 16)))
+		return false;
 
-	switch (dcbent->type) {
+	switch (dcb->type) {
 	case OUTPUT_TMDS:
 	case OUTPUT_LVDS:
 	case OUTPUT_DP:
-		break;
-	default:
-		match_link = false;
-		break;
-	}
-
-	for (i = 0; i < record_nr; i++, record += record_len) {
-		table = ROM16(bios->data[record]);
-		if (!table)
-			continue;
-		entry = ROM32(bios->data[table]);
-
-		if (match_link) {
-			v = (entry & 0x00c00000) >> 22;
-			if (!(v & dcbent->sorconf.link))
-				continue;
+		if (hash & 0x00c00000) {
+			if (!(hash & (dcb->sorconf.link << 22)))
+				return false;
 		}
-
-		v = (entry & 0x000f0000) >> 16;
-		if (!(v & dcbent->or))
-			continue;
-
-		v = (entry & 0x000000f0) >> 4;
-		if (v != dcbent->location)
-			continue;
-
-		v = (entry & 0x0000000f);
-		if (v != dcbent->type)
-			continue;
-
-		return &bios->data[table];
+	default:
+		return true;
 	}
-
-	return NULL;
 }
 
 void *
@@ -4483,7 +4460,8 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nvbios *bios = &dev_priv->vbios;
-	uint8_t *table;
+	uint8_t *table, *entry;
+	int i;
 
 	if (!bios->display.dp_table_ptr) {
 		NV_ERROR(dev, "No pointer to DisplayPort table\n");
@@ -4497,10 +4475,17 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
 		return NULL;
 	}
 
-	*headerlen = table[4];
-	return bios_output_config_match(dev, dcbent,
-					bios->display.dp_table_ptr + table[1],
-					table[2], table[3], table[0] >= 0x21);
+	entry = table + table[1];
+	for (i = 0; i < table[3]; i++, entry += table[2]) {
+		u8 *etable = ROMPTR(bios, entry[0]);
+		if (etable && bios_encoder_match(dcbent, ROM32(etable[0]))) {
+			*headerlen = table[4];
+			return etable;
+		}
+	}
+
+	NV_ERROR(dev, "DisplayPort encoder table not found\n");
+	return NULL;
 }
 
 int
@@ -4535,7 +4520,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk,
 	uint8_t *table = &bios->data[bios->display.script_table_ptr];
 	uint8_t *otable = NULL;
 	uint16_t script;
-	int i = 0;
+	int i;
 
 	if (!bios->display.script_table_ptr) {
 		NV_ERROR(dev, "No pointer to output script table\n");
@@ -4587,9 +4572,12 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk,
 
 	NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n",
 			dcbent->type, dcbent->location, dcbent->or);
-	otable = bios_output_config_match(dev, dcbent, table[1] +
-					  bios->display.script_table_ptr,
-					  table[2], table[3], table[0] >= 0x21);
+	for (i = 0; i < table[3]; i++) {
+		otable = ROMPTR(bios, table[table[1] + (i * table[2])]);
+		if (otable && bios_encoder_match(dcbent, ROM32(otable[0])))
+			break;
+	}
+
 	if (!otable) {
 		NV_DEBUG_KMS(dev, "failed to match any output table\n");
 		return 1;

+ 1 - 0
drivers/gpu/drm/nouveau/nouveau_drv.h

@@ -1090,6 +1090,7 @@ extern int run_tmds_table(struct drm_device *, struct dcb_entry *,
 			  int head, int pxclk);
 extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head,
 			    enum LVDS_script, int pxclk);
+bool bios_encoder_match(struct dcb_entry *, u32 hash);
 
 /* nouveau_ttm.c */
 int nouveau_ttm_global_init(struct drm_nouveau_private *);