Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 218208
b: refs/heads/master
c: e49f70f
h: refs/heads/master
v: v3
  • Loading branch information
Ben Skeggs committed Sep 24, 2010
1 parent af2ea05 commit 60d6efb
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 94 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 07b1266962085412e85af2e7df471ec9ed0c35f5
refs/heads/master: e49f70f775335ab1ee0ecd54904d2b25982a2600
156 changes: 63 additions & 93 deletions trunk/drivers/gpu/drm/nouveau/nouveau_bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -5762,8 +5762,14 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len)
static struct dcb_gpio_entry *
new_gpio_entry(struct nvbios *bios)
{
struct drm_device *dev = bios->dev;
struct dcb_gpio_table *gpio = &bios->dcb.gpio;

if (gpio->entries >= DCB_MAX_NUM_GPIO_ENTRIES) {
NV_ERROR(dev, "exceeded maximum number of gpio entries!!\n");
return NULL;
}

return &gpio->entry[gpio->entries++];
}

Expand All @@ -5784,114 +5790,78 @@ nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag)
return NULL;
}

static void
parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset)
{
struct dcb_gpio_entry *gpio;
uint16_t ent = ROM16(bios->data[offset]);
uint8_t line = ent & 0x1f,
tag = ent >> 5 & 0x3f,
flags = ent >> 11 & 0x1f;

if (tag == 0x3f)
return;

gpio = new_gpio_entry(bios);

gpio->tag = tag;
gpio->line = line;
gpio->invert = flags != 4;
gpio->entry = ent;
}

static void
parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset)
{
uint32_t entry = ROM32(bios->data[offset]);
struct dcb_gpio_entry *gpio;

if ((entry & 0x0000ff00) == 0x0000ff00)
return;

gpio = new_gpio_entry(bios);
gpio->tag = (entry & 0x0000ff00) >> 8;
gpio->line = (entry & 0x0000001f) >> 0;
gpio->state_default = (entry & 0x01000000) >> 24;
gpio->state[0] = (entry & 0x18000000) >> 27;
gpio->state[1] = (entry & 0x60000000) >> 29;
gpio->entry = entry;
}

static void
parse_dcb_gpio_table(struct nvbios *bios)
{
struct drm_device *dev = bios->dev;
uint16_t gpio_table_ptr = bios->dcb.gpio_table_ptr;
uint8_t *gpio_table = &bios->data[gpio_table_ptr];
int header_len = gpio_table[1],
entries = gpio_table[2],
entry_len = gpio_table[3];
void (*parse_entry)(struct nvbios *, uint16_t) = NULL;
struct dcb_gpio_entry *e;
u8 headerlen, entries, recordlen;
u8 *dcb, *gpio = NULL, *entry;
int i;

if (bios->dcb.version >= 0x40) {
if (gpio_table_ptr && entry_len != 4) {
NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
return;
}

parse_entry = parse_dcb40_gpio_entry;

} else if (bios->dcb.version >= 0x30) {
if (gpio_table_ptr && entry_len != 2) {
NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
return;
}

parse_entry = parse_dcb30_gpio_entry;
dcb = ROMPTR(bios, bios->data[0x36]);
if (dcb[0] >= 0x30) {
gpio = ROMPTR(bios, dcb[10]);
if (!gpio)
goto no_table;

} else if (bios->dcb.version >= 0x22) {
/*
* DCBs older than v3.0 don't really have a GPIO
* table, instead they keep some GPIO info at fixed
* locations.
*/
uint16_t dcbptr = ROM16(bios->data[0x36]);
uint8_t *tvdac_gpio = &bios->data[dcbptr - 5];
headerlen = gpio[1];
entries = gpio[2];
recordlen = gpio[3];
} else
if (dcb[0] >= 0x22) {
gpio = ROMPTR(bios, dcb[-15]);
if (!gpio)
goto no_table;

headerlen = 3;
entries = gpio[2];
recordlen = gpio[1];
} else {
NV_DEBUG(dev, "no/unknown gpio table on DCB 0x%02x\n", dcb[0]);
goto no_table;
}

if (tvdac_gpio[0] & 1) {
struct dcb_gpio_entry *gpio = new_gpio_entry(bios);
entry = gpio + headerlen;
for (i = 0; i < entries; i++, entry += recordlen) {
e = new_gpio_entry(bios);
if (!e)
break;

gpio->tag = DCB_GPIO_TVDAC0;
gpio->line = tvdac_gpio[1] >> 4;
gpio->invert = tvdac_gpio[0] & 2;
}
} else {
/*
* No systematic way to store GPIO info on pre-v2.2
* DCBs, try to match the PCI device IDs.
*/
if (gpio[0] < 0x40) {
e->entry = ROM16(entry[0]);
e->tag = (e->entry & 0x07e0) >> 5;
if (e->tag == 0x3f) {
bios->dcb.gpio.entries--;
continue;
}

/* Apple iMac G4 NV18 */
if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) {
struct dcb_gpio_entry *gpio = new_gpio_entry(bios);
e->line = (e->entry & 0x001f);
e->invert = ((e->entry & 0xf800) >> 11) != 4;
} else {
e->entry = ROM32(entry[0]);
e->tag = (e->entry & 0x0000ff00) >> 8;
if (e->tag == 0xff) {
bios->dcb.gpio.entries--;
continue;
}

gpio->tag = DCB_GPIO_TVDAC0;
gpio->line = 4;
e->line = (e->entry & 0x0000001f) >> 0;
e->state_default = (e->entry & 0x01000000) >> 24;
e->state[0] = (e->entry & 0x18000000) >> 27;
e->state[1] = (e->entry & 0x60000000) >> 29;
}

}

if (!gpio_table_ptr)
return;

if (entries > DCB_MAX_NUM_GPIO_ENTRIES) {
NV_WARN(dev, "Too many entries in the DCB GPIO table.\n");
entries = DCB_MAX_NUM_GPIO_ENTRIES;
no_table:
/* Apple iMac G4 NV18 */
if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) {
e = new_gpio_entry(bios);
if (e) {
e->tag = DCB_GPIO_TVDAC0;
e->line = 4;
}
}

for (i = 0; i < entries; i++)
parse_entry(bios, gpio_table_ptr + header_len + entry_len * i);
}

struct dcb_connector_table_entry *
Expand Down

0 comments on commit 60d6efb

Please sign in to comment.