Merge branch 'intelfb-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied...
[linux-drm-fsl-dcu.git] / drivers / video / intelfb / intelfbdrv.c
index 06af89d44a0ddc90e06ab7db005de0843d96014a..6f9de04193d216d62f62511f7bbb0cd821d3c0df 100644 (file)
 static void __devinit get_initial_mode(struct intelfb_info *dinfo);
 static void update_dinfo(struct intelfb_info *dinfo,
                         struct fb_var_screeninfo *var);
+static int intelfb_open(struct fb_info *info, int user);
+static int intelfb_release(struct fb_info *info, int user);
 static int intelfb_check_var(struct fb_var_screeninfo *var,
                             struct fb_info *info);
 static int intelfb_set_par(struct fb_info *info);
@@ -194,6 +196,8 @@ static int num_registered = 0;
 /* fb ops */
 static struct fb_ops intel_fb_ops = {
        .owner =                THIS_MODULE,
+       .fb_open =              intelfb_open,
+       .fb_release =           intelfb_release,
        .fb_check_var =         intelfb_check_var,
        .fb_set_par =           intelfb_set_par,
        .fb_setcolreg =         intelfb_setcolreg,
@@ -446,6 +450,8 @@ cleanup(struct intelfb_info *dinfo)
        if (!dinfo)
                return;
 
+       intelfbhw_disable_irq(dinfo);
+
        fb_dealloc_cmap(&dinfo->info->cmap);
        kfree(dinfo->info->pixmap.addr);
 
@@ -467,6 +473,11 @@ cleanup(struct intelfb_info *dinfo)
                agp_free_memory(dinfo->gtt_ring_mem);
        }
 
+#ifdef CONFIG_FB_INTEL_I2C
+       /* un-register I2C bus */
+       intelfb_delete_i2c_busses(dinfo);
+#endif
+
        if (dinfo->mmio_base)
                iounmap((void __iomem *)dinfo->mmio_base);
        if (dinfo->aperture.virtual)
@@ -844,6 +855,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (bailearly == 5)
                bailout(dinfo);
 
+#ifdef CONFIG_FB_INTEL_I2C
+       /* register I2C bus */
+       intelfb_create_i2c_busses(dinfo);
+#endif
+
        if (bailearly == 6)
                bailout(dinfo);
 
@@ -888,6 +904,13 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        dinfo->registered = 1;
+       dinfo->open = 0;
+
+       init_waitqueue_head(&dinfo->vsync.wait);
+       spin_lock_init(&dinfo->int_lock);
+       dinfo->irq_flags = 0;
+       dinfo->vsync.pan_display = 0;
+       dinfo->vsync.pan_offset = 0;
 
        return 0;
 
@@ -1187,6 +1210,34 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
  *                       fbdev interface                       *
  ***************************************************************/
 
+static int
+intelfb_open(struct fb_info *info, int user)
+{
+       struct intelfb_info *dinfo = GET_DINFO(info);
+
+       if (user) {
+               dinfo->open++;
+       }
+
+       return 0;
+}
+
+static int
+intelfb_release(struct fb_info *info, int user)
+{
+       struct intelfb_info *dinfo = GET_DINFO(info);
+
+       if (user) {
+               dinfo->open--;
+               msleep(1);
+               if (!dinfo->open) {
+                       intelfbhw_disable_irq(dinfo);
+               }
+       }
+
+       return 0;
+}
+
 static int
 intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
@@ -1433,6 +1484,19 @@ static int
 intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 {
        int retval = 0;
+       struct intelfb_info *dinfo = GET_DINFO(info);
+       u32 pipe = 0;
+
+       switch (cmd) {
+               case FBIO_WAITFORVSYNC:
+                       if (get_user(pipe, (__u32 __user *)arg))
+                               return -EFAULT;
+
+                       retval = intelfbhw_wait_for_vsync(dinfo, pipe);
+                       break;
+               default:
+                       break;
+       }
 
        return retval;
 }