aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv10_gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv10_gpio.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv10_gpio.c117
1 files changed, 43 insertions, 74 deletions
diff --git a/drivers/gpu/drm/nouveau/nv10_gpio.c b/drivers/gpu/drm/nouveau/nv10_gpio.c
index 550ad3f..007fc29 100644
--- a/drivers/gpu/drm/nouveau/nv10_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv10_gpio.c
@@ -27,97 +27,66 @@
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_hw.h"
-#include "nouveau_gpio.h"
-int
-nv10_gpio_sense(struct drm_device *dev, int line)
+static bool
+get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift,
+ uint32_t *mask)
{
- if (line < 2) {
- line = line * 16;
- line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO) >> line;
- return !!(line & 0x0100);
- } else
- if (line < 10) {
- line = (line - 2) * 4;
- line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT) >> line;
- return !!(line & 0x04);
- } else
- if (line < 14) {
- line = (line - 10) * 4;
- line = NVReadCRTC(dev, 0, NV_PCRTC_850) >> line;
- return !!(line & 0x04);
- }
+ if (ent->line < 2) {
+ *reg = NV_PCRTC_GPIO;
+ *shift = ent->line * 16;
+ *mask = 0x11;
- return -EINVAL;
-}
+ } else if (ent->line < 10) {
+ *reg = NV_PCRTC_GPIO_EXT;
+ *shift = (ent->line - 2) * 4;
+ *mask = 0x3;
+
+ } else if (ent->line < 14) {
+ *reg = NV_PCRTC_850;
+ *shift = (ent->line - 10) * 4;
+ *mask = 0x3;
-int
-nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out)
-{
- u32 reg, mask, data;
-
- if (line < 2) {
- line = line * 16;
- reg = NV_PCRTC_GPIO;
- mask = 0x00000011;
- data = (dir << 4) | out;
- } else
- if (line < 10) {
- line = (line - 2) * 4;
- reg = NV_PCRTC_GPIO_EXT;
- mask = 0x00000003 << ((line - 2) * 4);
- data = (dir << 1) | out;
- } else
- if (line < 14) {
- line = (line - 10) * 4;
- reg = NV_PCRTC_850;
- mask = 0x00000003;
- data = (dir << 1) | out;
} else {
- return -EINVAL;
+ return false;
}
- mask = NVReadCRTC(dev, 0, reg) & ~(mask << line);
- NVWriteCRTC(dev, 0, reg, mask | (data << line));
- return 0;
+ return true;
}
-void
-nv10_gpio_irq_enable(struct drm_device *dev, int line, bool on)
+int
+nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
{
- u32 mask = 0x00010001 << line;
+ struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
+ uint32_t reg, shift, mask, value;
- nv_wr32(dev, 0x001104, mask);
- nv_mask(dev, 0x001144, mask, on ? mask : 0);
-}
+ if (!ent)
+ return -ENODEV;
-static void
-nv10_gpio_isr(struct drm_device *dev)
-{
- u32 intr = nv_rd32(dev, 0x1104);
- u32 hi = (intr & 0x0000ffff) >> 0;
- u32 lo = (intr & 0xffff0000) >> 16;
+ if (!get_gpio_location(ent, &reg, &shift, &mask))
+ return -ENODEV;
- nouveau_gpio_isr(dev, 0, hi | lo);
+ value = NVReadCRTC(dev, 0, reg) >> shift;
- nv_wr32(dev, 0x001104, intr);
+ return (ent->invert ? 1 : 0) ^ (value & 1);
}
int
-nv10_gpio_init(struct drm_device *dev)
+nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
{
- nv_wr32(dev, 0x001140, 0x00000000);
- nv_wr32(dev, 0x001100, 0xffffffff);
- nv_wr32(dev, 0x001144, 0x00000000);
- nv_wr32(dev, 0x001104, 0xffffffff);
- nouveau_irq_register(dev, 28, nv10_gpio_isr); /* PBUS */
- return 0;
-}
+ struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
+ uint32_t reg, shift, mask, value;
-void
-nv10_gpio_fini(struct drm_device *dev)
-{
- nv_wr32(dev, 0x001140, 0x00000000);
- nv_wr32(dev, 0x001144, 0x00000000);
- nouveau_irq_unregister(dev, 28);
+ if (!ent)
+ return -ENODEV;
+
+ if (!get_gpio_location(ent, &reg, &shift, &mask))
+ return -ENODEV;
+
+ value = ((ent->invert ? 1 : 0) ^ (state ? 1 : 0)) << shift;
+ mask = ~(mask << shift);
+
+ NVWriteCRTC(dev, 0, reg, value | (NVReadCRTC(dev, 0, reg) & mask));
+
+ return 0;
}