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;
* 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
};
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);
}
/*
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,
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);
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:
}
omapfb_rqueue_unlock(fbdev);
+ if (do_update)
+ omapfb_update_full_screen(fbdev);
+
DBGLEAVE(1);
return r;
}
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;
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)
{
* 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;
} p;
int r = 0;
- DBGENTER(2);
-
BUG_ON(!ops);
DBGPRINT(2, "cmd=%010x\n", cmd);
switch (cmd)
(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)))
}
}
-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) {
}
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;
}
* 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);
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;
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);
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;
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);
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,
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)
{