Commit 1ed73166 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/bios: implement opcode 0xa9

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent d2bcea68
...@@ -11,7 +11,7 @@ struct nouveau_gpio { ...@@ -11,7 +11,7 @@ struct nouveau_gpio {
struct nouveau_subdev base; struct nouveau_subdev base;
/* hardware interfaces */ /* hardware interfaces */
void (*reset)(struct nouveau_gpio *); void (*reset)(struct nouveau_gpio *, u8 func);
int (*drive)(struct nouveau_gpio *, int line, int dir, int out); int (*drive)(struct nouveau_gpio *, int line, int dir, int out);
int (*sense)(struct nouveau_gpio *, int line); int (*sense)(struct nouveau_gpio *, int line);
void (*irq_enable)(struct nouveau_gpio *, int line, bool); void (*irq_enable)(struct nouveau_gpio *, int line, bool);
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
#include <core/device.h> #include <core/device.h>
#include <subdev/bios.h> #include <subdev/bios.h>
#include <subdev/bios/conn.h>
#include <subdev/bios/bmp.h> #include <subdev/bios/bmp.h>
#include <subdev/bios/bit.h> #include <subdev/bios/bit.h>
#include <subdev/bios/conn.h>
#include <subdev/bios/dcb.h> #include <subdev/bios/dcb.h>
#include <subdev/bios/dp.h> #include <subdev/bios/dp.h>
#include <subdev/bios/gpio.h>
#include <subdev/bios/init.h> #include <subdev/bios/init.h>
#include <subdev/devinit.h> #include <subdev/devinit.h>
#include <subdev/clock.h> #include <subdev/clock.h>
...@@ -1781,7 +1782,7 @@ init_gpio(struct nvbios_init *init) ...@@ -1781,7 +1782,7 @@ init_gpio(struct nvbios_init *init)
init->offset += 1; init->offset += 1;
if (init_exec(init) && gpio && gpio->reset) if (init_exec(init) && gpio && gpio->reset)
gpio->reset(gpio); gpio->reset(gpio, DCB_GPIO_UNUSED);
} }
/** /**
...@@ -1995,6 +1996,47 @@ init_i2c_long_if(struct nvbios_init *init) ...@@ -1995,6 +1996,47 @@ init_i2c_long_if(struct nvbios_init *init)
init_exec_set(init, false); init_exec_set(init, false);
} }
/**
* INIT_GPIO_NE - opcode 0xa9
*
*/
static void
init_gpio_ne(struct nvbios_init *init)
{
struct nouveau_bios *bios = init->bios;
struct nouveau_gpio *gpio = nouveau_gpio(bios);
struct dcb_gpio_func func;
u8 count = nv_ro08(bios, init->offset + 1);
u8 idx = 0, ver, len;
u16 data, i;
trace("GPIO_NE\t");
init->offset += 2;
for (i = init->offset; i < init->offset + count; i++)
cont("0x%02x ", nv_ro08(bios, i));
cont("\n");
while ((data = dcb_gpio_parse(bios, 0, idx++, &ver, &len, &func))) {
if (func.func != DCB_GPIO_UNUSED) {
for (i = init->offset; i < init->offset + count; i++) {
if (func.func == nv_ro08(bios, i))
break;
}
trace("\tFUNC[0x%02x]", func.func);
if (i == (init->offset + count)) {
cont(" *");
if (init_exec(init) && gpio && gpio->reset)
gpio->reset(gpio, func.func);
}
cont("\n");
}
}
init->offset += count;
}
static struct nvbios_init_opcode { static struct nvbios_init_opcode {
void (*exec)(struct nvbios_init *); void (*exec)(struct nvbios_init *);
} init_opcode[] = { } init_opcode[] = {
...@@ -2059,6 +2101,7 @@ static struct nvbios_init_opcode { ...@@ -2059,6 +2101,7 @@ static struct nvbios_init_opcode {
[0x98] = { init_auxch }, [0x98] = { init_auxch },
[0x99] = { init_zm_auxch }, [0x99] = { init_zm_auxch },
[0x9a] = { init_i2c_long_if }, [0x9a] = { init_i2c_long_if },
[0xa9] = { init_gpio_ne },
}; };
#define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0]))
......
...@@ -270,7 +270,7 @@ nouveau_gpio_init(struct nouveau_gpio *gpio) ...@@ -270,7 +270,7 @@ nouveau_gpio_init(struct nouveau_gpio *gpio)
int ret = nouveau_subdev_init(&gpio->base); int ret = nouveau_subdev_init(&gpio->base);
if (ret == 0 && gpio->reset) { if (ret == 0 && gpio->reset) {
if (dmi_check_system(gpio_reset_ids)) if (dmi_check_system(gpio_reset_ids))
gpio->reset(gpio); gpio->reset(gpio, DCB_GPIO_UNUSED);
} }
return ret; return ret;
} }
...@@ -29,7 +29,7 @@ struct nv50_gpio_priv { ...@@ -29,7 +29,7 @@ struct nv50_gpio_priv {
}; };
static void static void
nv50_gpio_reset(struct nouveau_gpio *gpio) nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
{ {
struct nouveau_bios *bios = nouveau_bios(gpio); struct nouveau_bios *bios = nouveau_bios(gpio);
struct nv50_gpio_priv *priv = (void *)gpio; struct nv50_gpio_priv *priv = (void *)gpio;
...@@ -48,7 +48,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio) ...@@ -48,7 +48,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio)
u32 val = (unk1 << 16) | unk0; u32 val = (unk1 << 16) | unk0;
u32 reg = regs[line >> 4]; line &= 0x0f; u32 reg = regs[line >> 4]; line &= 0x0f;
if (func == 0xff) if ( func == DCB_GPIO_UNUSED ||
(match != DCB_GPIO_UNUSED && match != func))
continue; continue;
gpio->set(gpio, 0, func, line, defs); gpio->set(gpio, 0, func, line, defs);
......
...@@ -29,7 +29,7 @@ struct nvd0_gpio_priv { ...@@ -29,7 +29,7 @@ struct nvd0_gpio_priv {
}; };
static void static void
nvd0_gpio_reset(struct nouveau_gpio *gpio) nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match)
{ {
struct nouveau_bios *bios = nouveau_bios(gpio); struct nouveau_bios *bios = nouveau_bios(gpio);
struct nvd0_gpio_priv *priv = (void *)gpio; struct nvd0_gpio_priv *priv = (void *)gpio;
...@@ -45,7 +45,8 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio) ...@@ -45,7 +45,8 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio)
u8 unk0 = (data & 0x00ff0000) >> 16; u8 unk0 = (data & 0x00ff0000) >> 16;
u8 unk1 = (data & 0x1f000000) >> 24; u8 unk1 = (data & 0x1f000000) >> 24;
if (func == 0xff) if ( func == DCB_GPIO_UNUSED ||
(match != DCB_GPIO_UNUSED && match != func))
continue; continue;
gpio->set(gpio, 0, func, line, defs); gpio->set(gpio, 0, func, line, defs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment