drm/nvd0/gpio: initial implementation
authorBen Skeggs <bskeggs@redhat.com>
Sat, 2 Jul 2011 16:57:35 +0000 (02:57 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 20 Sep 2011 06:05:36 +0000 (16:05 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv50_gpio.c

index b311faba34f8450916de4f732d3f5ba48fe28bd2..30e723c81069c9e73330db07871a96b6c9efcf72 100644 (file)
@@ -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;
+                       }
                }
        }
 
index 7fdfad03f96c3baa96a1f74d61ad477390fa0a82..721845add9b2f0a8ca0eb85be1a373e43ea76003 100644 (file)
@@ -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,
index 10b201102231bcc0b6cf4760822bf4d9f8ac1d6e..8cf42e223fc3654657e26ba3baf11ae20238c56f 100644 (file)
@@ -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;
index d4f4206dad7ef18cbf1bb7e96435b653a4d940d1..793a5ccca12157319e5393490fd0783dc97c6b59 100644 (file)
@@ -97,6 +97,37 @@ nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
        return 0;
 }
 
+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)