diff options
author | Jonathan Corbet <corbet@lwn.net> | 2010-04-23 09:46:59 -0600 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2010-05-07 17:17:38 -0600 |
commit | 94dd1a856b23bd51dfebf68e6dd63cfd4d4fd5ae (patch) | |
tree | 32d573966e60cf0b2b41e785015366f6a2eeff0e /drivers/video/via/via-core.c | |
parent | 6b841edf572ad757f11013326b796e126f05a719 (diff) |
viafb: Add a simple interrupt management infrastructure
The viafb device shares a single interrupt control register among several
distinct subunits. This adds a simple layer for management of that
register.
Cc: ScottFang@viatech.com.cn
Cc: JosephChan@via.com.tw
Cc: Harald Welte <laforge@gnumonks.org>
Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Diffstat (limited to 'drivers/video/via/via-core.c')
-rw-r--r-- | drivers/video/via/via-core.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index 5a78ef9cb382..701b95575747 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -35,6 +35,65 @@ static struct viafb_dev global_dev; /* + * Basic register access; spinlock required. + */ +static inline void viafb_mmio_write(int reg, u32 v) +{ + iowrite32(v, global_dev.engine_mmio + reg); +} + +static inline int viafb_mmio_read(int reg) +{ + return ioread32(global_dev.engine_mmio + reg); +} + +/* ---------------------------------------------------------------------- */ +/* + * Interrupt management. We have a single IRQ line for a lot of + * different functions, so we need to share it. The design here + * is that we don't want to reimplement the shared IRQ code here; + * we also want to avoid having contention for a single handler thread. + * So each subdev driver which needs interrupts just requests + * them directly from the kernel. We just have what's needed for + * overall access to the interrupt control register. + */ + +/* + * Which interrupts are enabled now? + */ +static u32 viafb_enabled_ints; + +static void viafb_int_init(void) +{ + viafb_enabled_ints = 0; + + viafb_mmio_write(VDE_INTERRUPT, 0); +} + +/* + * Allow subdevs to ask for specific interrupts to be enabled. These + * functions must be called with reg_lock held + */ +void viafb_irq_enable(u32 mask) +{ + viafb_enabled_ints |= mask; + viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE); +} +EXPORT_SYMBOL_GPL(viafb_irq_enable); + +void viafb_irq_disable(u32 mask) +{ + viafb_enabled_ints &= ~mask; + if (viafb_enabled_ints == 0) + viafb_mmio_write(VDE_INTERRUPT, 0); /* Disable entirely */ + else + viafb_mmio_write(VDE_INTERRUPT, + viafb_enabled_ints | VDE_I_ENABLE); +} +EXPORT_SYMBOL_GPL(viafb_irq_disable); + + +/* * Figure out how big our framebuffer memory is. Kind of ugly, * but evidently we can't trust the information found in the * fbdev configuration area. @@ -275,8 +334,10 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, if (ret) goto out_disable; /* - * Create our subdevices. Continue even if some things fail. + * Set up interrupts and create our subdevices. Continue even if + * some things fail. */ + viafb_int_init(); via_setup_subdevs(&global_dev); /* * Set up the framebuffer. @@ -284,6 +345,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, ret = via_fb_pci_probe(&global_dev); if (ret) goto out_subdevs; + return 0; out_subdevs: |