]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/video/omap/omapfb_main.c
[PATCH] ARM: OMAP: OMAP: FB: sem2mutex conversion
[linux-2.6-omap-h63xx.git] / drivers / video / omap / omapfb_main.c
index 2c4098d578fc05ae01b8e723a7785527f4dbbed4..7e783790f396bea91602720e05cb225d26fc097e 100644 (file)
@@ -67,6 +67,10 @@ static int           manual_update = 1;
 static int             manual_update;
 #endif
 
+static struct platform_device  *fbdev_pdev;
+static struct lcd_panel                *fbdev_panel;
+static struct omapfb_device    *omapfb_dev;
+
 static struct caps_table_struct {
         unsigned long flag;
         const char *name;
@@ -80,60 +84,20 @@ static struct caps_table_struct {
  * LCD panel
  * ---------------------------------------------------------------------------
  */
-extern struct lcd_panel h4_panel;
-extern struct lcd_panel h3_panel;
-extern struct lcd_panel h2_panel;
-extern struct lcd_panel p2_panel;
-extern struct lcd_panel osk_panel;
-extern struct lcd_panel palmte_panel;
-extern struct lcd_panel innovator1610_panel;
-extern struct lcd_panel innovator1510_panel;
-extern struct lcd_panel lph8923_panel;
-
-static struct lcd_panel *panels[] = {
-#ifdef CONFIG_MACH_OMAP_H2
-       &h2_panel,
-#endif
-#ifdef CONFIG_MACH_OMAP_H3
-       &h3_panel,
-#endif
-#ifdef CONFIG_MACH_OMAP_H4
-       &h4_panel,
-#endif
-#ifdef CONFIG_MACH_OMAP_PERSEUS2
-       &p2_panel,
-#endif
-#ifdef CONFIG_MACH_OMAP_OSK
-       &osk_panel,
-#endif
-#ifdef CONFIG_MACH_OMAP_PALMTE
-       &palmte_panel,
-#endif
-
-#ifdef CONFIG_MACH_OMAP_INNOVATOR
-
-#ifdef CONFIG_ARCH_OMAP15XX
-       &innovator1510_panel,
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       &innovator1610_panel,
-#endif
-
-#endif
-};
-
 extern struct lcd_ctrl omap1_int_ctrl;
 extern struct lcd_ctrl omap2_int_ctrl;
 extern struct lcd_ctrl hwa742_ctrl;
 extern struct lcd_ctrl blizzard_ctrl;
 
 static struct lcd_ctrl *ctrls[] = {
-#ifdef CONFIG_FB_OMAP_LCDC_INTERNAL
 #ifdef CONFIG_ARCH_OMAP1
        &omap1_int_ctrl,
 #else
        &omap2_int_ctrl,
 #endif
+
+#ifdef CONFIG_FB_OMAP_LCDC_HWA742
+       &hwa742_ctrl,
 #endif
 };
 
@@ -147,12 +111,12 @@ extern struct lcd_ctrl_extif rfbi_extif;
 
 static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
 {
-       down(&fbdev->rqueue_sema);
+       mutex_lock(&fbdev->rqueue_mutex);
 }
 
 static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
 {
-       up(&fbdev->rqueue_sema);
+       mutex_unlock(&fbdev->rqueue_mutex);
 }
 
 /*
@@ -188,7 +152,6 @@ static int ctrl_init(struct omapfb_device *fbdev)
 
        fbdev->ctrl->get_vram_layout(&fbdev->vram_size, &fbdev->vram_virt_base,
                                     &fbdev->vram_phys_base);
-       memset((void *)fbdev->vram_virt_base, 0, fbdev->vram_size);
 
        DBGPRINT(1, "vram_phys %08x vram_virt %p vram_size=%lu\n",
                 fbdev->vram_phys_base, fbdev->vram_virt_base,
@@ -335,12 +298,24 @@ static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
        return 0;
 }
 
+static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       struct omapfb_device *fbdev = info->par;
+       int r;
+
+       omapfb_rqueue_lock(fbdev);
+       r = fbdev->ctrl->mmap(vma);
+       omapfb_rqueue_unlock(fbdev);
+
+       return r;
+}
 
 static void omapfb_update_full_screen(struct omapfb_device *fbdev);
 
 static int omapfb_blank(int blank, struct fb_info *fbi)
 {
        struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+       int do_update = 0;
        int r = 0;
 
        DBGENTER(1);
@@ -349,20 +324,20 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
        switch (blank) {
        case VESA_NO_BLANKING:
                if (fbdev->state == OMAPFB_SUSPENDED) {
-                       fbdev->panel->enable();
                        if (fbdev->ctrl->resume)
                                fbdev->ctrl->resume();
+                       fbdev->panel->enable();
                        fbdev->state = OMAPFB_ACTIVE;
                        if (fbdev->ctrl->get_update_mode() ==
                                        OMAPFB_MANUAL_UPDATE)
-                               omapfb_update_full_screen(fbdev);
+                               do_update = 1;
                }
                break;
        case VESA_POWERDOWN:
                if (fbdev->state == OMAPFB_ACTIVE) {
+                       fbdev->panel->disable();
                        if (fbdev->ctrl->suspend)
                                fbdev->ctrl->suspend();
-                       fbdev->panel->disable();
                        fbdev->state = OMAPFB_SUSPENDED;
                }
                break;
@@ -371,6 +346,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
        }
        omapfb_rqueue_unlock(fbdev);
 
+       if (do_update)
+               omapfb_update_full_screen(fbdev);
+
        DBGLEAVE(1);
        return r;
 }
@@ -602,28 +580,52 @@ static int omapfb_set_par(struct fb_info *fbi)
        return r;
 }
 
-static int omapfb_update_win(struct omapfb_device *fbdev,
-                               struct omapfb_update_window *win)
+int omapfb_update_window_async(struct omapfb_update_window *win,
+                                       void (*callback)(void *),
+                                       void *callback_data)
 {
-       struct fb_var_screeninfo *var = &fbdev->fb_info->var;
-       int ret;
+       struct omapfb_device *fbdev = omapfb_dev;
+       struct fb_var_screeninfo *var;
 
-       if (win->x >= var->xres || win->y >= var->yres)
+       DBGENTER(2);
+       if (fbdev == NULL) {
+               DBGPRINT(1, "no fbdev\n");
+               return -ENODEV;
+       }
+
+       var = &fbdev->fb_info->var;
+
+       if (win->x >= var->xres || win->y >= var->yres) {
+               DBGPRINT(1, "invalid x %d, y %d\n", win->x, win->y);
                return -EINVAL;
+       }
 
        if (!fbdev->ctrl->update_window ||
-           fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+           fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) {
+               DBGPRINT(1, "invalid update mode\n");
                return -ENODEV;
+       }
 
        if (win->x + win->width >= var->xres)
                win->width = var->xres - win->x;
        if (win->y + win->height >= var->yres)
                win->height = var->yres - win->y;
-       if (!win->width || !win->height)
+       if (!win->width || !win->height) {
+               DBGPRINT(1, "zero size window\n");
                return 0;
+       }
+
+       return fbdev->ctrl->update_window(win, callback, callback_data);
+}
+EXPORT_SYMBOL(omapfb_update_window_async);
+
+static int omapfb_update_win(struct omapfb_device *fbdev,
+                               struct omapfb_update_window *win)
+{
+       int ret;
 
        omapfb_rqueue_lock(fbdev);
-       ret = fbdev->ctrl->update_window(win, NULL, 0);
+       ret = omapfb_update_window_async(win, NULL, 0);
        omapfb_rqueue_unlock(fbdev);
 
        return ret;
@@ -685,6 +687,45 @@ static int omapfb_set_color_key(struct omapfb_device *fbdev,
        return r;
 }
 
+static struct notifier_block *omapfb_client_list;
+
+int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
+                           omapfb_notifier_callback_t callback,
+                           void *callback_data)
+{
+       int r;
+
+       DBGENTER(1);
+
+       omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *,
+                                       unsigned long, void *))callback;
+       omapfb_nb->data = callback_data;
+       r = notifier_chain_register(&omapfb_client_list, &omapfb_nb->nb);
+       if (r)
+               return r;
+       if (omapfb_dev != NULL &&
+           omapfb_dev->ctrl && omapfb_dev->ctrl->bind_client) {
+               omapfb_dev->ctrl->bind_client(omapfb_nb);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(omapfb_register_client);
+
+int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb)
+{
+       return notifier_chain_unregister(&omapfb_client_list,
+                                        &omapfb_nb->nb);
+}
+EXPORT_SYMBOL(omapfb_unregister_client);
+
+void omapfb_notify_clients(struct omapfb_device *fbdev, unsigned long event)
+{
+       DBGENTER(1);
+       notifier_call_chain(&omapfb_client_list, event, fbdev);
+}
+EXPORT_SYMBOL(omapfb_notify_clients);
+
 static int omapfb_set_update_mode(struct omapfb_device *fbdev,
                                   enum omapfb_update_mode mode)
 {
@@ -743,9 +784,8 @@ EXPORT_SYMBOL(omapfb_write_first_pixel);
  * graphics transformations, frame flipping support is provided through this
  * interface.
  */
-static int omapfb_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg,
-                       struct fb_info *fbi)
+static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
+                       unsigned long arg)
 {
        struct omapfb_device    *fbdev = (struct omapfb_device *)fbi->par;
        struct fb_ops           *ops = fbi->fbops;
@@ -760,8 +800,6 @@ static int omapfb_ioctl(struct inode *inode, struct file *file,
        } p;
        int r = 0;
 
-       DBGENTER(2);
-
        BUG_ON(!ops);
        DBGPRINT(2, "cmd=%010x\n", cmd);
        switch (cmd)
@@ -789,6 +827,15 @@ static int omapfb_ioctl(struct inode *inode, struct file *file,
                                        (enum omapfb_update_mode __user *)arg))
                        r = -EFAULT;
                break;
+       case OMAPFB_UPDATE_WINDOW_OLD:
+               if (copy_from_user(&p.update_window, (void __user *)arg,
+                                  sizeof(struct omapfb_update_window_old)))
+                       r = -EFAULT;
+               else {
+                       p.update_window.format = 0;
+                       r = omapfb_update_win(fbdev, &p.update_window);
+               }
+               break;
        case OMAPFB_UPDATE_WINDOW:
                if (copy_from_user(&p.update_window, (void __user *)arg,
                                   sizeof(p.update_window)))
@@ -1108,11 +1155,12 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
        switch (state) {
        case OMAPFB_ACTIVE:
                unregister_framebuffer(fbdev->fb_info);
-       case 6:
+       case 7:
                omapfb_unregister_sysfs(fbdev);
-               omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
-       case 5:
+       case 6:
                fbdev->panel->disable();
+       case 5:
+               omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
        case 4:
                fbinfo_cleanup(fbdev);
        case 3:
@@ -1130,45 +1178,21 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
        }
 }
 
-static int omapfb_find_panel(struct omapfb_device *fbdev)
-{
-       const struct omap_lcd_config *conf;
-       char name[17];
-       int i;
-
-       conf = (struct omap_lcd_config *)fbdev->dev->platform_data;
-       fbdev->panel = NULL;
-       if (conf == NULL)
-               return -1;
-
-       strncpy(name, conf->panel_name, sizeof(name) - 1);
-       name[sizeof(name) - 1] = 0;
-       for (i = 0; i < ARRAY_SIZE(panels); i++) {
-               if (strcmp(panels[i]->name, name) == 0) {
-                       fbdev->panel = panels[i];
-                       break;
-               }
-       }
-
-       if (fbdev->panel == NULL)
-               return -1;
-
-       return 0;
-}
-
 static int omapfb_find_ctrl(struct omapfb_device *fbdev)
 {
-       struct omap_lcd_config *conf;
+       struct omapfb_platform_data *conf;
        char name[17];
        int i;
 
-       conf = (struct omap_lcd_config *)fbdev->dev->platform_data;
+       conf = (struct omapfb_platform_data *)fbdev->dev->platform_data;
 
        fbdev->ctrl = NULL;
-       if (conf == NULL)
+       if (conf == NULL) {
+               DBGPRINT(1, "omap_lcd_config not found\n");
                return -1;
+       }
 
-       strncpy(name, conf->ctrl_name, sizeof(name) - 1);
+       strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1);
        name[sizeof(name) - 1] = '\0';
 
        if (strcmp(name, "internal") == 0) {
@@ -1177,14 +1201,17 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev)
        }
 
        for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
+               DBGPRINT(1, "ctrl %s\n", ctrls[i]->name);
                if (strcmp(ctrls[i]->name, name) == 0) {
                        fbdev->ctrl = ctrls[i];
                        break;
                }
        }
 
-       if (fbdev->ctrl == NULL)
+       if (fbdev->ctrl == NULL) {
+               DBGPRINT(1, "ctrl %s not supported\n", name);
                return -1;
+       }
 
        return 0;
 }
@@ -1214,13 +1241,12 @@ static void check_required_callbacks(struct omapfb_device *fbdev)
  *      start LCD frame transfer
  *   7. register system fb_info structure
  */
-static int omapfb_probe(struct platform_device *pdev)
+static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel)
 {
        struct omapfb_device    *fbdev = NULL;
        struct fb_info          *fbi;
        int                     init_state;
        unsigned long           phz, hhz, vhz;
-       struct lcd_panel        *panel;
        int                     r = 0;
 
        DBGENTER(1);
@@ -1244,9 +1270,10 @@ static int omapfb_probe(struct platform_device *pdev)
        fbdev = (struct omapfb_device *)fbi->par;
        fbdev->fb_info = fbi;
        fbdev->dev = &pdev->dev;
+       fbdev->panel = panel;
        platform_set_drvdata(pdev, fbdev);
 
-       init_MUTEX(&fbdev->rqueue_sema);
+       mutex_init(&fbdev->rqueue_mutex);
 
 #ifdef CONFIG_ARCH_OMAP1
        fbdev->int_ctrl = &omap1_int_ctrl;
@@ -1265,15 +1292,6 @@ static int omapfb_probe(struct platform_device *pdev)
                goto cleanup;
        }
 
-       if (omapfb_find_panel(fbdev) < 0) {
-               pr_err("LCD panel not found, board not supported\n");
-               r = -ENODEV;
-               goto cleanup;
-       }
-
-       check_required_callbacks(fbdev);
-
-
        pr_info(MODULE_NAME ": configured for panel %s\n", fbdev->panel->name);
 
        r = fbdev->panel->init(fbdev);
@@ -1286,6 +1304,14 @@ static int omapfb_probe(struct platform_device *pdev)
                goto cleanup;
        init_state++;
 
+       /* We depend on doing this after ctrl_init, since it can redefine
+        * member functions.
+        */
+       if (fbdev->ctrl->mmap)
+               omapfb_ops.fb_mmap = omapfb_mmap;
+
+       check_required_callbacks(fbdev);
+
        r = fbinfo_init(fbdev);
        if (r)
                goto cleanup;
@@ -1296,21 +1322,23 @@ static int omapfb_probe(struct platform_device *pdev)
        omap_set_dma_priority(OMAP_DMA_PORT_EMIFF, 15);
 #endif
 
-       r = fbdev->panel->enable();
-       if (r)
-               goto cleanup;
-       init_state++;
-
        r = ctrl_change_mode(fbdev);
        if (r) {
                pr_err("mode setting failed\n");
                goto cleanup;
        }
 
-       omapfb_enable_plane(fbdev, 0, 1);
+       if (!manual_update)
+               omapfb_enable_plane(fbdev, OMAPFB_PLANE_GFX, 1);
 
        omapfb_set_update_mode(fbdev, manual_update ?
                                   OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
+       init_state++;
+
+       r = fbdev->panel->enable();
+       if (r)
+               goto cleanup;
+       init_state++;
 
        r = omapfb_register_sysfs(fbdev);
        if (r)
@@ -1330,6 +1358,8 @@ static int omapfb_probe(struct platform_device *pdev)
        hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw);
        vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw);
 
+       omapfb_dev = fbdev;
+
        pr_info(MODULE_NAME ": initialized vram=%lu "
                        "pixclock %lu kHz hfreq %lu.%lu kHz vfreq %lu.%lu Hz\n",
                        fbdev->vram_size,
@@ -1345,6 +1375,27 @@ cleanup:
        return r;
 }
 
+static int omapfb_probe(struct platform_device *pdev)
+{
+       BUG_ON(fbdev_pdev != NULL);
+
+       DBGENTER(1);
+       fbdev_pdev = pdev;
+       if (fbdev_panel != NULL)
+               omapfb_do_probe(fbdev_pdev, fbdev_panel);
+       return 0;
+}
+
+void omapfb_register_panel(struct lcd_panel *panel)
+{
+       BUG_ON(fbdev_panel != NULL);
+
+       DBGENTER(1);
+       fbdev_panel = panel;
+       if (fbdev_pdev != NULL)
+               omapfb_do_probe(fbdev_pdev, fbdev_panel);
+}
+
 /* Called when the device is being detached from the driver */
 static int omapfb_remove(struct platform_device *pdev)
 {