diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-07-03 02:57:35 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-09-20 16:05:36 +1000 |
commit | d7f8172ca93b61135d6db293c6440b2e97fc87ee (patch) | |
tree | a3124b1956a2cacdacb0d04035996415484f6357 | |
parent | eeb3ca12b4658c569bd60fe60c4c45c627e842a6 (diff) | |
download | op-kernel-dev-d7f8172ca93b61135d6db293c6440b2e97fc87ee.zip op-kernel-dev-d7f8172ca93b61135d6db293c6440b2e97fc87ee.tar.gz |
drm/nvd0/gpio: initial implementation
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_gpio.c | 31 |
4 files changed, 48 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index b311fab..30e723c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -5884,9 +5884,15 @@ parse_dcb_gpio_table(struct nvbios *bios) } 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[0] == 0x40) { + e->state_default = (e->entry & 0x01000000) >> 24; + e->state[0] = (e->entry & 0x18000000) >> 27; + e->state[1] = (e->entry & 0x60000000) >> 29; + } else { + e->state_default = (e->entry & 0x00000080) >> 7; + e->state[0] = (entry[4] >> 4) & 3; + e->state[1] = (entry[4] >> 6) & 3; + } } } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 7fdfad0..721845ad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1391,6 +1391,8 @@ int nv50_gpio_init(struct drm_device *dev); void nv50_gpio_fini(struct drm_device *dev); int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); +int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, void (*)(void *, int), void *); void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 10b2011..8cf42e2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -459,8 +459,13 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.create = nouveau_stub_init; engine->display.init = nouveau_stub_init; engine->display.destroy = nouveau_stub_takedown; - engine->gpio.init = nouveau_stub_init; + engine->gpio.init = nv50_gpio_init; engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.get = nvd0_gpio_get; + engine->gpio.set = nvd0_gpio_set; + engine->gpio.irq_register = nv50_gpio_irq_register; + engine->gpio.irq_unregister = nv50_gpio_irq_unregister; + engine->gpio.irq_enable = nv50_gpio_irq_enable; engine->vram.init = nvc0_vram_init; engine->vram.takedown = nv50_vram_fini; engine->vram.get = nvc0_vram_new; diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index d4f4206..793a5cc 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -98,6 +98,37 @@ nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) } int +nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) +{ + struct dcb_gpio_entry *gpio; + u32 v; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return -ENOENT; + + v = nv_rd32(dev, 0x00d610 + (gpio->line * 4)); + v &= 0x00004000; + return (!!v == (gpio->state[1] & 1)); +} + +int +nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) +{ + struct dcb_gpio_entry *gpio; + u32 v; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return -ENOENT; + + v = gpio->state[state] ^ 2; + + nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12); + return 0; +} + +int nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, void (*handler)(void *, int), void *data) { |