diff options
author | Eric Hustvedt <ehustvedt@cecropia.com> | 2006-06-20 14:36:41 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-07-03 04:59:46 -0400 |
commit | 7649757bd900bc900adcd95ab08903cdc28342fa (patch) | |
tree | 4c710d9e458ff3c6731180aca738123886f7adec /drivers/video/intelfb/intelfbhw.c | |
parent | 9a5f019b1a9ea6a75ba36d7c312ff069006ed479 (diff) |
intelfb: add vsync interrupt support
[03/05] intelfb: Implement basic interrupt handling
Functions have been added to enable and disable interrupts using the MMIO registers. Currently only pipe A vsync interrupts are enabled.
A generalized vsync accounting struct is defined, with the intent that it can encapsulate per-pipe vsync related info in the future. Currently a single instance is hard-coded.
The interrupt service routine currently only looks for vsync interrupts on pipe A, and increments a counter and wakes up anyone waiting on it.
This implementation is heavily influenced by similar implementations in the atyfb and matroxfb drivers.
Signed-off-by: Eric Hustvedt <ehustvedt@cecropia.com>
Diffstat (limited to 'drivers/video/intelfb/intelfbhw.c')
-rw-r--r-- | drivers/video/intelfb/intelfbhw.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 05aded669cdb..1a698a7230e0 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
36 | #include <linux/pagemap.h> | 36 | #include <linux/pagemap.h> |
37 | #include <linux/interrupt.h> | ||
37 | 38 | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | 40 | ||
@@ -1943,3 +1944,78 @@ intelfbhw_cursor_reset(struct intelfb_info *dinfo) { | |||
1943 | addr += 16; | 1944 | addr += 16; |
1944 | } | 1945 | } |
1945 | } | 1946 | } |
1947 | |||
1948 | static irqreturn_t | ||
1949 | intelfbhw_irq(int irq, void *dev_id, struct pt_regs *fp) { | ||
1950 | int handled = 0; | ||
1951 | u16 tmp; | ||
1952 | struct intelfb_info *dinfo = (struct intelfb_info *)dev_id; | ||
1953 | |||
1954 | spin_lock(&dinfo->int_lock); | ||
1955 | |||
1956 | tmp = INREG16(IIR); | ||
1957 | tmp &= VSYNC_PIPE_A_INTERRUPT; | ||
1958 | |||
1959 | if (tmp == 0) { | ||
1960 | spin_unlock(&dinfo->int_lock); | ||
1961 | return IRQ_RETVAL(handled); | ||
1962 | } | ||
1963 | |||
1964 | OUTREG16(IIR, tmp); | ||
1965 | |||
1966 | if (tmp & VSYNC_PIPE_A_INTERRUPT) { | ||
1967 | dinfo->vsync.count++; | ||
1968 | wake_up_interruptible(&dinfo->vsync.wait); | ||
1969 | handled = 1; | ||
1970 | } | ||
1971 | |||
1972 | spin_unlock(&dinfo->int_lock); | ||
1973 | |||
1974 | return IRQ_RETVAL(handled); | ||
1975 | } | ||
1976 | |||
1977 | int | ||
1978 | intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable) { | ||
1979 | |||
1980 | if (!test_and_set_bit(0, &dinfo->irq_flags)) { | ||
1981 | if (request_irq(dinfo->pdev->irq, intelfbhw_irq, SA_SHIRQ, "intelfb", dinfo)) { | ||
1982 | clear_bit(0, &dinfo->irq_flags); | ||
1983 | return -EINVAL; | ||
1984 | } | ||
1985 | |||
1986 | spin_lock_irq(&dinfo->int_lock); | ||
1987 | OUTREG16(HWSTAM, 0xfffe); | ||
1988 | OUTREG16(IMR, 0x0); | ||
1989 | OUTREG16(IER, VSYNC_PIPE_A_INTERRUPT); | ||
1990 | spin_unlock_irq(&dinfo->int_lock); | ||
1991 | } else if (reenable) { | ||
1992 | u16 ier; | ||
1993 | |||
1994 | spin_lock_irq(&dinfo->int_lock); | ||
1995 | ier = INREG16(IER); | ||
1996 | if ((ier & VSYNC_PIPE_A_INTERRUPT)) { | ||
1997 | DBG_MSG("someone disabled the IRQ [%08X]\n", ier); | ||
1998 | OUTREG(IER, VSYNC_PIPE_A_INTERRUPT); | ||
1999 | } | ||
2000 | spin_unlock_irq(&dinfo->int_lock); | ||
2001 | } | ||
2002 | return 0; | ||
2003 | } | ||
2004 | |||
2005 | void | ||
2006 | intelfbhw_disable_irq(struct intelfb_info *dinfo) { | ||
2007 | u16 tmp; | ||
2008 | |||
2009 | if (test_and_clear_bit(0, &dinfo->irq_flags)) { | ||
2010 | spin_lock_irq(&dinfo->int_lock); | ||
2011 | OUTREG16(HWSTAM, 0xffff); | ||
2012 | OUTREG16(IMR, 0xffff); | ||
2013 | OUTREG16(IER, 0x0); | ||
2014 | |||
2015 | tmp = INREG16(IIR); | ||
2016 | OUTREG16(IIR, tmp); | ||
2017 | spin_unlock_irq(&dinfo->int_lock); | ||
2018 | |||
2019 | free_irq(dinfo->pdev->irq, dinfo); | ||
2020 | } | ||
2021 | } | ||