|
@@ -155,6 +155,8 @@ struct resmap {
|
|
|
unsigned long *map;
|
|
|
};
|
|
|
|
|
|
+#define MAX_IRQ_HANDLERS 4
|
|
|
+
|
|
|
static struct {
|
|
|
void __iomem *base;
|
|
|
|
|
@@ -167,9 +169,11 @@ static struct {
|
|
|
|
|
|
int ext_mode;
|
|
|
|
|
|
- unsigned long enabled_irqs;
|
|
|
- void (*irq_callback)(void *);
|
|
|
- void *irq_callback_data;
|
|
|
+ struct {
|
|
|
+ u32 irq_mask;
|
|
|
+ void (*callback)(void *);
|
|
|
+ void *data;
|
|
|
+ } irq_handlers[MAX_IRQ_HANDLERS];
|
|
|
struct completion frame_done;
|
|
|
|
|
|
int fir_hinc[OMAPFB_PLANE_NUM];
|
|
@@ -809,56 +813,70 @@ static void set_lcd_timings(void)
|
|
|
panel->pixel_clock = fck / lck_div / pck_div / 1000;
|
|
|
}
|
|
|
|
|
|
-int omap_dispc_request_irq(void (*callback)(void *data), void *data)
|
|
|
+static void recalc_irq_mask(void)
|
|
|
{
|
|
|
- int r = 0;
|
|
|
+ int i;
|
|
|
+ unsigned long irq_mask = DISPC_IRQ_MASK_ERROR;
|
|
|
|
|
|
- BUG_ON(callback == NULL);
|
|
|
+ for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
|
|
|
+ if (!dispc.irq_handlers[i].callback)
|
|
|
+ continue;
|
|
|
|
|
|
- if (dispc.irq_callback)
|
|
|
- r = -EBUSY;
|
|
|
- else {
|
|
|
- dispc.irq_callback = callback;
|
|
|
- dispc.irq_callback_data = data;
|
|
|
+ irq_mask |= dispc.irq_handlers[i].irq_mask;
|
|
|
}
|
|
|
|
|
|
- return r;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(omap_dispc_request_irq);
|
|
|
-
|
|
|
-void omap_dispc_enable_irqs(int irq_mask)
|
|
|
-{
|
|
|
enable_lcd_clocks(1);
|
|
|
- dispc.enabled_irqs = irq_mask;
|
|
|
- irq_mask |= DISPC_IRQ_MASK_ERROR;
|
|
|
MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
|
|
|
enable_lcd_clocks(0);
|
|
|
}
|
|
|
-EXPORT_SYMBOL(omap_dispc_enable_irqs);
|
|
|
|
|
|
-void omap_dispc_disable_irqs(int irq_mask)
|
|
|
+int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data),
|
|
|
+ void *data)
|
|
|
{
|
|
|
- enable_lcd_clocks(1);
|
|
|
- dispc.enabled_irqs &= ~irq_mask;
|
|
|
- irq_mask &= ~DISPC_IRQ_MASK_ERROR;
|
|
|
- MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
|
|
|
- enable_lcd_clocks(0);
|
|
|
+ int i;
|
|
|
+
|
|
|
+ BUG_ON(callback == NULL);
|
|
|
+
|
|
|
+ for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
|
|
|
+ if (dispc.irq_handlers[i].callback)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ dispc.irq_handlers[i].irq_mask = irq_mask;
|
|
|
+ dispc.irq_handlers[i].callback = callback;
|
|
|
+ dispc.irq_handlers[i].data = data;
|
|
|
+ recalc_irq_mask();
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -EBUSY;
|
|
|
}
|
|
|
-EXPORT_SYMBOL(omap_dispc_disable_irqs);
|
|
|
+EXPORT_SYMBOL(omap_dispc_request_irq);
|
|
|
|
|
|
-void omap_dispc_free_irq(void)
|
|
|
+void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data),
|
|
|
+ void *data)
|
|
|
{
|
|
|
- enable_lcd_clocks(1);
|
|
|
- omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL);
|
|
|
- dispc.irq_callback = NULL;
|
|
|
- dispc.irq_callback_data = NULL;
|
|
|
- enable_lcd_clocks(0);
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
|
|
|
+ if (dispc.irq_handlers[i].callback == callback &&
|
|
|
+ dispc.irq_handlers[i].data == data) {
|
|
|
+ dispc.irq_handlers[i].irq_mask = 0;
|
|
|
+ dispc.irq_handlers[i].callback = NULL;
|
|
|
+ dispc.irq_handlers[i].data = NULL;
|
|
|
+ recalc_irq_mask();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ BUG();
|
|
|
}
|
|
|
EXPORT_SYMBOL(omap_dispc_free_irq);
|
|
|
|
|
|
static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
|
|
|
{
|
|
|
u32 stat;
|
|
|
+ int i = 0;
|
|
|
|
|
|
enable_lcd_clocks(1);
|
|
|
|
|
@@ -873,8 +891,12 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if ((stat & dispc.enabled_irqs) && dispc.irq_callback)
|
|
|
- dispc.irq_callback(dispc.irq_callback_data);
|
|
|
+ for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
|
|
|
+ if (unlikely(dispc.irq_handlers[i].callback &&
|
|
|
+ (stat & dispc.irq_handlers[i].irq_mask)))
|
|
|
+ dispc.irq_handlers[i].callback(
|
|
|
+ dispc.irq_handlers[i].data);
|
|
|
+ }
|
|
|
|
|
|
dispc_write_reg(DISPC_IRQSTATUS, stat);
|
|
|
|
|
@@ -1410,8 +1432,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
|
|
|
l = dispc_read_reg(DISPC_IRQSTATUS);
|
|
|
dispc_write_reg(DISPC_IRQSTATUS, l);
|
|
|
|
|
|
- /* Enable those that we handle always */
|
|
|
- omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
|
|
|
+ recalc_irq_mask();
|
|
|
|
|
|
if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
|
|
|
0, MODULE_NAME, fbdev)) < 0) {
|