summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-04-07 12:00:14 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-04-09 10:15:44 +1000
commit2535d71c80b3d79090c9d44ec6d35342e2d258f0 (patch)
tree9d0cc01bd721e1d3ae749fce66c2c80635b212e7
parent2295e17a4a0c339ca8507deb2cab5f339007e5e5 (diff)
downloadlinux-2535d71c80b3d79090c9d44ec6d35342e2d258f0.tar.gz
drm/nouveau: store raw gpio table entry in bios gpio structs
And use our own version of the GPIO table for the INIT_GPIO opcode.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c48
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.h1
2 files changed, 21 insertions, 28 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index ad6c2d4520ae..84b03e0a3865 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -2573,48 +2573,38 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 	 * each GPIO according to various values listed in each entry
 	 */
 
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
 	const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
 	const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
-	const uint8_t *gpio_table = &bios->data[bios->dcb.gpio_table_ptr];
-	const uint8_t *gpio_entry;
 	int i;
 
-	if (!iexec->execute)
-		return 1;
-
-	if (bios->dcb.version != 0x40) {
-		NV_ERROR(bios->dev, "DCB table not version 4.0\n");
-		return 0;
-	}
-
-	if (!bios->dcb.gpio_table_ptr) {
-		NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
-		return 0;
+	if (dev_priv->card_type != NV_50) {
+		NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n");
+		return -ENODEV;
 	}
 
-	gpio_entry = gpio_table + gpio_table[1];
-	for (i = 0; i < gpio_table[2]; i++, gpio_entry += gpio_table[3]) {
-		uint32_t entry = ROM32(gpio_entry[0]), r, s, v;
-		int line = (entry & 0x0000001f);
+	if (!iexec->execute)
+		return 1;
 
-		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, entry);
+	for (i = 0; i < bios->dcb.gpio.entries; i++) {
+		struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i];
+		uint32_t r, s, v;
 
-		if ((entry & 0x0000ff00) == 0x0000ff00)
-			continue;
+		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
 
-		r = nv50_gpio_reg[line >> 3];
-		s = (line & 0x07) << 2;
+		r = nv50_gpio_reg[gpio->line >> 3];
+		s = (gpio->line & 0x07) << 2;
 		v = bios_rd32(bios, r) & ~(0x00000003 << s);
-		if (entry & 0x01000000)
-			v |= (((entry & 0x60000000) >> 29) ^ 2) << s;
+		if (gpio->entry & 0x01000000)
+			v |= (((gpio->entry & 0x60000000) >> 29) ^ 2) << s;
 		else
-			v |= (((entry & 0x18000000) >> 27) ^ 2) << s;
+			v |= (((gpio->entry & 0x18000000) >> 27) ^ 2) << s;
 		bios_wr32(bios, r, v);
 
-		r = nv50_gpio_ctl[line >> 4];
-		s = (line & 0x0f);
+		r = nv50_gpio_ctl[gpio->line >> 4];
+		s = (gpio->line & 0x0f);
 		v = bios_rd32(bios, r) & ~(0x00010001 << s);
-		switch ((entry & 0x06000000) >> 25) {
+		switch ((gpio->entry & 0x06000000) >> 25) {
 		case 1:
 			v |= (0x00000001 << s);
 			break;
@@ -5082,6 +5072,7 @@ parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset)
 	gpio->tag = tag;
 	gpio->line = line;
 	gpio->invert = flags != 4;
+	gpio->entry = ent;
 }
 
 static void
@@ -5101,6 +5092,7 @@ parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset)
 	 * point. */
 	gpio->tag = tag;
 	gpio->line = line;
+	gpio->entry = ent;
 }
 
 static void
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index fd6274a90148..3706493c014d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -49,6 +49,7 @@ struct dcb_gpio_entry {
 	enum dcb_gpio_tag tag;
 	int line;
 	bool invert;
+	uint32_t entry;
 };
 
 struct dcb_gpio_table {