diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-02-13 15:31:38 +0200 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-04-17 08:10:19 +0300 |
commit | f7018c21350204c4cf628462f229d44d03545254 (patch) | |
tree | 408787177164cf51cc06f7aabdb04fcff8d2b6aa /drivers/video/omap2/omapfb | |
parent | c26ef3eb3c11274bad1b64498d0a134f85755250 (diff) | |
download | linux-f7018c21350204c4cf628462f229d44d03545254.tar.gz |
video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related
files, directories for backlight, console, linux logo, lots of fbdev
device drivers, fbdev framework files.
Make some order into the chaos by creating drivers/video/fbdev
directory, and move all fbdev related files there.
No functionality is changed, although I guess it is possible that some
subtle Makefile build order related issue could be created by this
patch.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Rob Clark <robdclark@gmail.com>
Acked-by: Jingoo Han <jg1.han@samsung.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/video/omap2/omapfb')
-rw-r--r-- | drivers/video/omap2/omapfb/Kconfig | 27 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-ioctl.c | 922 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 2656 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-sysfs.c | 605 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb.h | 208 |
6 files changed, 0 insertions, 4420 deletions
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig deleted file mode 100644 index 4cb12ce68855..000000000000 --- a/drivers/video/omap2/omapfb/Kconfig +++ /dev/null @@ -1,27 +0,0 @@ -menuconfig FB_OMAP2 - tristate "OMAP2+ frame buffer support" - depends on FB && OMAP2_DSS && !DRM_OMAP - - select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Frame buffer driver for OMAP2+ based boards. - -config FB_OMAP2_DEBUG_SUPPORT - bool "Debug support for OMAP2+ FB" - default y - depends on FB_OMAP2 - help - Support for debug output. You have to enable the actual printing - with 'debug' module parameter. - -config FB_OMAP2_NUM_FBS - int "Number of framebuffers" - range 1 10 - default 3 - depends on FB_OMAP2 - help - Select the number of framebuffers created. OMAP2/3 has 3 overlays - so normally this would be 3. diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile deleted file mode 100644 index 51c2e00d9bf8..000000000000 --- a/drivers/video/omap2/omapfb/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_FB_OMAP2) += omapfb.o -omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c deleted file mode 100644 index 146b6f5428db..000000000000 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ /dev/null @@ -1,922 +0,0 @@ -/* - * linux/drivers/video/omap2/omapfb-ioctl.c - * - * Copyright (C) 2008 Nokia Corporation - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> - * - * Some code and ideas taken from drivers/video/omap/ driver - * by Imre Deak. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/fb.h> -#include <linux/device.h> -#include <linux/uaccess.h> -#include <linux/platform_device.h> -#include <linux/mm.h> -#include <linux/omapfb.h> -#include <linux/vmalloc.h> -#include <linux/export.h> -#include <linux/sizes.h> - -#include <video/omapdss.h> -#include <video/omapvrfb.h> - -#include "omapfb.h" - -static u8 get_mem_idx(struct omapfb_info *ofbi) -{ - if (ofbi->id == ofbi->region->id) - return 0; - - return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id; -} - -static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi, - u8 mem_idx) -{ - struct omapfb2_device *fbdev = ofbi->fbdev; - - if (mem_idx & OMAPFB_MEM_IDX_ENABLED) - mem_idx &= OMAPFB_MEM_IDX_MASK; - else - mem_idx = ofbi->id; - - if (mem_idx >= fbdev->num_fbs) - return NULL; - - return &fbdev->regions[mem_idx]; -} - -static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omap_overlay *ovl; - struct omap_overlay_info old_info; - struct omapfb2_mem_region *old_rg, *new_rg; - int r = 0; - - DBG("omapfb_setup_plane\n"); - - if (ofbi->num_overlays == 0) { - r = -EINVAL; - goto out; - } - - /* XXX uses only the first overlay */ - ovl = ofbi->overlays[0]; - - old_rg = ofbi->region; - new_rg = get_mem_region(ofbi, pi->mem_idx); - if (!new_rg) { - r = -EINVAL; - goto out; - } - - /* Take the locks in a specific order to keep lockdep happy */ - if (old_rg->id < new_rg->id) { - omapfb_get_mem_region(old_rg); - omapfb_get_mem_region(new_rg); - } else if (new_rg->id < old_rg->id) { - omapfb_get_mem_region(new_rg); - omapfb_get_mem_region(old_rg); - } else - omapfb_get_mem_region(old_rg); - - if (pi->enabled && !new_rg->size) { - /* - * This plane's memory was freed, can't enable it - * until it's reallocated. - */ - r = -EINVAL; - goto put_mem; - } - - ovl->get_overlay_info(ovl, &old_info); - - if (old_rg != new_rg) { - ofbi->region = new_rg; - set_fb_fix(fbi); - } - - if (!pi->enabled) { - r = ovl->disable(ovl); - if (r) - goto undo; - } - - if (pi->enabled) { - r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y, - pi->out_width, pi->out_height); - if (r) - goto undo; - } else { - struct omap_overlay_info info; - - ovl->get_overlay_info(ovl, &info); - - info.pos_x = pi->pos_x; - info.pos_y = pi->pos_y; - info.out_width = pi->out_width; - info.out_height = pi->out_height; - - r = ovl->set_overlay_info(ovl, &info); - if (r) - goto undo; - } - - if (ovl->manager) - ovl->manager->apply(ovl->manager); - - if (pi->enabled) { - r = ovl->enable(ovl); - if (r) - goto undo; - } - - /* Release the locks in a specific order to keep lockdep happy */ - if (old_rg->id > new_rg->id) { - omapfb_put_mem_region(old_rg); - omapfb_put_mem_region(new_rg); - } else if (new_rg->id > old_rg->id) { - omapfb_put_mem_region(new_rg); - omapfb_put_mem_region(old_rg); - } else - omapfb_put_mem_region(old_rg); - - return 0; - - undo: - if (old_rg != new_rg) { - ofbi->region = old_rg; - set_fb_fix(fbi); - } - - ovl->set_overlay_info(ovl, &old_info); - put_mem: - /* Release the locks in a specific order to keep lockdep happy */ - if (old_rg->id > new_rg->id) { - omapfb_put_mem_region(old_rg); - omapfb_put_mem_region(new_rg); - } else if (new_rg->id > old_rg->id) { - omapfb_put_mem_region(new_rg); - omapfb_put_mem_region(old_rg); - } else - omapfb_put_mem_region(old_rg); - out: - dev_err(fbdev->dev, "setup_plane failed\n"); - - return r; -} - -static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - - if (ofbi->num_overlays == 0) { - memset(pi, 0, sizeof(*pi)); - } else { - struct omap_overlay *ovl; - struct omap_overlay_info ovli; - - ovl = ofbi->overlays[0]; - ovl->get_overlay_info(ovl, &ovli); - - pi->pos_x = ovli.pos_x; - pi->pos_y = ovli.pos_y; - pi->enabled = ovl->is_enabled(ovl); - pi->channel_out = 0; /* xxx */ - pi->mirror = 0; - pi->mem_idx = get_mem_idx(ofbi); - pi->out_width = ovli.out_width; - pi->out_height = ovli.out_height; - } - - return 0; -} - -static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omap_dss_device *display = fb2display(fbi); - struct omapfb2_mem_region *rg; - int r = 0, i; - size_t size; - - if (mi->type != OMAPFB_MEMTYPE_SDRAM) - return -EINVAL; - - size = PAGE_ALIGN(mi->size); - - if (display && display->driver->sync) - display->driver->sync(display); - - rg = ofbi->region; - - down_write_nested(&rg->lock, rg->id); - atomic_inc(&rg->lock_count); - - if (rg->size == size && rg->type == mi->type) - goto out; - - if (atomic_read(&rg->map_count)) { - r = -EBUSY; - goto out; - } - - for (i = 0; i < fbdev->num_fbs; i++) { - struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]); - int j; - - if (ofbi2->region != rg) - continue; - - for (j = 0; j < ofbi2->num_overlays; j++) { - struct omap_overlay *ovl; - ovl = ofbi2->overlays[j]; - if (ovl->is_enabled(ovl)) { - r = -EBUSY; - goto out; - } - } - } - - r = omapfb_realloc_fbmem(fbi, size, mi->type); - if (r) { - dev_err(fbdev->dev, "realloc fbmem failed\n"); - goto out; - } - - out: - atomic_dec(&rg->lock_count); - up_write(&rg->lock); - - return r; -} - -static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_mem_region *rg; - - rg = omapfb_get_mem_region(ofbi->region); - memset(mi, 0, sizeof(*mi)); - - mi->size = rg->size; - mi->type = rg->type; - - omapfb_put_mem_region(rg); - - return 0; -} - -static int omapfb_update_window(struct fb_info *fbi, - u32 x, u32 y, u32 w, u32 h) -{ - struct omap_dss_device *display = fb2display(fbi); - u16 dw, dh; - - if (!display) - return 0; - - if (w == 0 || h == 0) - return 0; - - display->driver->get_resolution(display, &dw, &dh); - - if (x + w > dw || y + h > dh) - return -EINVAL; - - return display->driver->update(display, x, y, w, h); -} - -int omapfb_set_update_mode(struct fb_info *fbi, - enum omapfb_update_mode mode) -{ - struct omap_dss_device *display = fb2display(fbi); - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omapfb_display_data *d; - int r; - - if (!display) - return -EINVAL; - - if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE) - return -EINVAL; - - omapfb_lock(fbdev); - - d = get_display_data(fbdev, display); - - if (d->update_mode == mode) { - omapfb_unlock(fbdev); - return 0; - } - - r = 0; - - if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { - if (mode == OMAPFB_AUTO_UPDATE) - omapfb_start_auto_update(fbdev, display); - else /* MANUAL_UPDATE */ - omapfb_stop_auto_update(fbdev, display); - - d->update_mode = mode; - } else { /* AUTO_UPDATE */ - if (mode == OMAPFB_MANUAL_UPDATE) - r = -EINVAL; - } - - omapfb_unlock(fbdev); - - return r; -} - -int omapfb_get_update_mode(struct fb_info *fbi, - enum omapfb_update_mode *mode) -{ - struct omap_dss_device *display = fb2display(fbi); - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omapfb_display_data *d; - - if (!display) - return -EINVAL; - - omapfb_lock(fbdev); - - d = get_display_data(fbdev, display); - - *mode = d->update_mode; - - omapfb_unlock(fbdev); - - return 0; -} - -/* XXX this color key handling is a hack... */ -static struct omapfb_color_key omapfb_color_keys[2]; - -static int _omapfb_set_color_key(struct omap_overlay_manager *mgr, - struct omapfb_color_key *ck) -{ - struct omap_overlay_manager_info info; - enum omap_dss_trans_key_type kt; - int r; - - mgr->get_manager_info(mgr, &info); - - if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) { - info.trans_enabled = false; - omapfb_color_keys[mgr->id] = *ck; - - r = mgr->set_manager_info(mgr, &info); - if (r) - return r; - - r = mgr->apply(mgr); - - return r; - } - - switch (ck->key_type) { - case OMAPFB_COLOR_KEY_GFX_DST: - kt = OMAP_DSS_COLOR_KEY_GFX_DST; - break; - case OMAPFB_COLOR_KEY_VID_SRC: - kt = OMAP_DSS_COLOR_KEY_VID_SRC; - break; - default: - return -EINVAL; - } - - info.default_color = ck->background; - info.trans_key = ck->trans_key; - info.trans_key_type = kt; - info.trans_enabled = true; - - omapfb_color_keys[mgr->id] = *ck; - - r = mgr->set_manager_info(mgr, &info); - if (r) - return r; - - r = mgr->apply(mgr); - - return r; -} - -static int omapfb_set_color_key(struct fb_info *fbi, - struct omapfb_color_key *ck) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - int r; - int i; - struct omap_overlay_manager *mgr = NULL; - - omapfb_lock(fbdev); - - for (i = 0; i < ofbi->num_overlays; i++) { - if (ofbi->overlays[i]->manager) { - mgr = ofbi->overlays[i]->manager; - break; - } - } - - if (!mgr) { - r = -EINVAL; - goto err; - } - - r = _omapfb_set_color_key(mgr, ck); -err: - omapfb_unlock(fbdev); - - return r; -} - -static int omapfb_get_color_key(struct fb_info *fbi, - struct omapfb_color_key *ck) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omap_overlay_manager *mgr = NULL; - int r = 0; - int i; - - omapfb_lock(fbdev); - - for (i = 0; i < ofbi->num_overlays; i++) { - if (ofbi->overlays[i]->manager) { - mgr = ofbi->overlays[i]->manager; - break; - } - } - - if (!mgr) { - r = -EINVAL; - goto err; - } - - *ck = omapfb_color_keys[mgr->id]; -err: - omapfb_unlock(fbdev); - - return r; -} - -static int omapfb_memory_read(struct fb_info *fbi, - struct omapfb_memory_read *mr) -{ - struct omap_dss_device *display = fb2display(fbi); - void *buf; - int r; - - if (!display || !display->driver->memory_read) - return -ENOENT; - - if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size)) - return -EFAULT; - - if (mr->w * mr->h * 3 > mr->buffer_size) - return -EINVAL; - - buf = vmalloc(mr->buffer_size); - if (!buf) { - DBG("vmalloc failed\n"); - return -ENOMEM; - } - - r = display->driver->memory_read(display, buf, mr->buffer_size, - mr->x, mr->y, mr->w, mr->h); - - if (r > 0) { - if (copy_to_user(mr->buffer, buf, mr->buffer_size)) - r = -EFAULT; - } - - vfree(buf); - - return r; -} - -static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev, - struct omapfb_ovl_colormode *mode) -{ - int ovl_idx = mode->overlay_idx; - int mode_idx = mode->mode_idx; - struct omap_overlay *ovl; - enum omap_color_mode supported_modes; - struct fb_var_screeninfo var; - int i; - - if (ovl_idx >= fbdev->num_overlays) - return -ENODEV; - ovl = fbdev->overlays[ovl_idx]; - supported_modes = ovl->supported_modes; - - mode_idx = mode->mode_idx; - - for (i = 0; i < sizeof(supported_modes) * 8; i++) { - if (!(supported_modes & (1 << i))) - continue; - /* - * It's possible that the FB doesn't support a mode - * that is supported by the overlay, so call the - * following here. - */ - if (dss_mode_to_fb_mode(1 << i, &var) < 0) - continue; - - mode_idx--; - if (mode_idx < 0) - break; - } - - if (i == sizeof(supported_modes) * 8) - return -ENOENT; - - mode->bits_per_pixel = var.bits_per_pixel; - mode->nonstd = var.nonstd; - mode->red = var.red; - mode->green = var.green; - mode->blue = var.blue; - mode->transp = var.transp; - - return 0; -} - -static int omapfb_wait_for_go(struct fb_info *fbi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - int r = 0; - int i; - - for (i = 0; i < ofbi->num_overlays; ++i) { - struct omap_overlay *ovl = ofbi->overlays[i]; - r = ovl->wait_for_go(ovl); - if (r) - break; - } - - return r; -} - -int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omap_dss_device *display = fb2display(fbi); - struct omap_overlay_manager *mgr; - - union { - struct omapfb_update_window_old uwnd_o; - struct omapfb_update_window uwnd; - struct omapfb_plane_info plane_info; - struct omapfb_caps caps; - struct omapfb_mem_info mem_info; - struct omapfb_color_key color_key; - struct omapfb_ovl_colormode ovl_colormode; - enum omapfb_update_mode update_mode; - int test_num; - struct omapfb_memory_read memory_read; - struct omapfb_vram_info vram_info; - struct omapfb_tearsync_info tearsync_info; - struct omapfb_display_info display_info; - u32 crt; - } p; - - int r = 0; - - switch (cmd) { - case OMAPFB_SYNC_GFX: - DBG("ioctl SYNC_GFX\n"); - if (!display || !display->driver->sync) { - /* DSS1 never returns an error here, so we neither */ - /*r = -EINVAL;*/ - break; - } - - r = display->driver->sync(display); - break; - - case OMAPFB_UPDATE_WINDOW_OLD: - DBG("ioctl UPDATE_WINDOW_OLD\n"); - if (!display || !display->driver->update) { - r = -EINVAL; - break; - } - - if (copy_from_user(&p.uwnd_o, - (void __user *)arg, - sizeof(p.uwnd_o))) { - r = -EFAULT; - break; - } - - r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y, - p.uwnd_o.width, p.uwnd_o.height); - break; - - case OMAPFB_UPDATE_WINDOW: - DBG("ioctl UPDATE_WINDOW\n"); - if (!display || !display->driver->update) { - r = -EINVAL; - break; - } - - if (copy_from_user(&p.uwnd, (void __user *)arg, - sizeof(p.uwnd))) { - r = -EFAULT; - break; - } - - r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y, - p.uwnd.width, p.uwnd.height); - break; - - case OMAPFB_SETUP_PLANE: - DBG("ioctl SETUP_PLANE\n"); - if (copy_from_user(&p.plane_info, (void __user *)arg, - sizeof(p.plane_info))) - r = -EFAULT; - else - r = omapfb_setup_plane(fbi, &p.plane_info); - break; - - case OMAPFB_QUERY_PLANE: - DBG("ioctl QUERY_PLANE\n"); - r = omapfb_query_plane(fbi, &p.plane_info); - if (r < 0) - break; - if (copy_to_user((void __user *)arg, &p.plane_info, - sizeof(p.plane_info))) - r = -EFAULT; - break; - - case OMAPFB_SETUP_MEM: - DBG("ioctl SETUP_MEM\n"); - if (copy_from_user(&p.mem_info, (void __user *)arg, - sizeof(p.mem_info))) - r = -EFAULT; - else - r = omapfb_setup_mem(fbi, &p.mem_info); - break; - - case OMAPFB_QUERY_MEM: - DBG("ioctl QUERY_MEM\n"); - r = omapfb_query_mem(fbi, &p.mem_info); - if (r < 0) - break; - if (copy_to_user((void __user *)arg, &p.mem_info, - sizeof(p.mem_info))) - r = -EFAULT; - break; - - case OMAPFB_GET_CAPS: - DBG("ioctl GET_CAPS\n"); - if (!display) { - r = -EINVAL; - break; - } - - memset(&p.caps, 0, sizeof(p.caps)); - if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) - p.caps.ctrl |= OMAPFB_CAPS_MANUAL_UPDATE; - if (display->caps & OMAP_DSS_DISPLAY_CAP_TEAR_ELIM) - p.caps.ctrl |= OMAPFB_CAPS_TEARSYNC; - - if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps))) - r = -EFAULT; - break; - - case OMAPFB_GET_OVERLAY_COLORMODE: - DBG("ioctl GET_OVERLAY_COLORMODE\n"); - if (copy_from_user(&p.ovl_colormode, (void __user *)arg, - sizeof(p.ovl_colormode))) { - r = -EFAULT; - break; - } - r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode); - if (r < 0) - break; - if (copy_to_user((void __user *)arg, &p.ovl_colormode, - sizeof(p.ovl_colormode))) - r = -EFAULT; - break; - - case OMAPFB_SET_UPDATE_MODE: - DBG("ioctl SET_UPDATE_MODE\n"); - if (get_user(p.update_mode, (int __user *)arg)) - r = -EFAULT; - else - r = omapfb_set_update_mode(fbi, p.update_mode); - break; - - case OMAPFB_GET_UPDATE_MODE: - DBG("ioctl GET_UPDATE_MODE\n"); - r = omapfb_get_update_mode(fbi, &p.update_mode); - if (r) - break; - if (put_user(p.update_mode, - (enum omapfb_update_mode __user *)arg)) - r = -EFAULT; - break; - - case OMAPFB_SET_COLOR_KEY: - DBG("ioctl SET_COLOR_KEY\n"); - if (copy_from_user(&p.color_key, (void __user *)arg, - sizeof(p.color_key))) - r = -EFAULT; - else - r = omapfb_set_color_key(fbi, &p.color_key); - break; - - case OMAPFB_GET_COLOR_KEY: - DBG("ioctl GET_COLOR_KEY\n"); - r = omapfb_get_color_key(fbi, &p.color_key); - if (r) - break; - if (copy_to_user((void __user *)arg, &p.color_key, - sizeof(p.color_key))) - r = -EFAULT; - break; - - case FBIO_WAITFORVSYNC: - if (get_user(p.crt, (__u32 __user *)arg)) { - r = -EFAULT; - break; - } - if (p.crt != 0) { - r = -ENODEV; - break; - } - /* FALLTHROUGH */ - - case OMAPFB_WAITFORVSYNC: - DBG("ioctl WAITFORVSYNC\n"); - - if (!display) { - r = -EINVAL; - break; - } - - mgr = omapdss_find_mgr_from_display(display); - if (!mgr) { - r = -EINVAL; - break; - } - - r = mgr->wait_for_vsync(mgr); - break; - - case OMAPFB_WAITFORGO: - DBG("ioctl WAITFORGO\n"); - if (!display) { - r = -EINVAL; - break; - } - - r = omapfb_wait_for_go(fbi); - break; - - /* LCD and CTRL tests do the same thing for backward - * compatibility */ - case OMAPFB_LCD_TEST: - DBG("ioctl LCD_TEST\n"); - if (get_user(p.test_num, (int __user *)arg)) { - r = -EFAULT; - break; - } - if (!display || !display->driver->run_test) { - r = -EINVAL; - break; - } - - r = display->driver->run_test(display, p.test_num); - - break; - - case OMAPFB_CTRL_TEST: - DBG("ioctl CTRL_TEST\n"); - if (get_user(p.test_num, (int __user *)arg)) { - r = -EFAULT; - break; - } - if (!display || !display->driver->run_test) { - r = -EINVAL; - break; - } - - r = display->driver->run_test(display, p.test_num); - - break; - - case OMAPFB_MEMORY_READ: - DBG("ioctl MEMORY_READ\n"); - - if (copy_from_user(&p.memory_read, (void __user *)arg, - sizeof(p.memory_read))) { - r = -EFAULT; - break; - } - - r = omapfb_memory_read(fbi, &p.memory_read); - - break; - - case OMAPFB_GET_VRAM_INFO: { - DBG("ioctl GET_VRAM_INFO\n"); - - /* - * We don't have the ability to get this vram info anymore. - * Fill in something that should keep the applications working. - */ - p.vram_info.total = SZ_1M * 64; - p.vram_info.free = SZ_1M * 64; - p.vram_info.largest_free_block = SZ_1M * 64; - - if (copy_to_user((void __user *)arg, &p.vram_info, - sizeof(p.vram_info))) - r = -EFAULT; - break; - } - - case OMAPFB_SET_TEARSYNC: { - DBG("ioctl SET_TEARSYNC\n"); - - if (copy_from_user(&p.tearsync_info, (void __user *)arg, - sizeof(p.tearsync_info))) { - r = -EFAULT; - break; - } - - if (!display || !display->driver->enable_te) { - r = -ENODEV; - break; - } - - r = display->driver->enable_te(display, - !!p.tearsync_info.enabled); - - break; - } - - case OMAPFB_GET_DISPLAY_INFO: { - u16 xres, yres; - - DBG("ioctl GET_DISPLAY_INFO\n"); - - if (display == NULL) { - r = -ENODEV; - break; - } - - display->driver->get_resolution(display, &xres, &yres); - - p.display_info.xres = xres; - p.display_info.yres = yres; - - if (display->driver->get_dimensions) { - u32 w, h; - display->driver->get_dimensions(display, &w, &h); - p.display_info.width = w; - p.display_info.height = h; - } else { - p.display_info.width = 0; - p.display_info.height = 0; - } - - if (copy_to_user((void __user *)arg, &p.display_info, - sizeof(p.display_info))) - r = -EFAULT; - break; - } - - default: - dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd); - r = -EINVAL; - } - - if (r < 0) - DBG("ioctl failed: %d\n", r); - - return r; -} - - diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c deleted file mode 100644 index ec2d132c782d..000000000000 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ /dev/null @@ -1,2656 +0,0 @@ -/* - * linux/drivers/video/omap2/omapfb-main.c - * - * Copyright (C) 2008 Nokia Corporation - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> - * - * Some code and ideas taken from drivers/video/omap/ driver - * by Imre Deak. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/fb.h> -#include <linux/dma-mapping.h> -#include <linux/vmalloc.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/omapfb.h> - -#include <video/omapdss.h> -#include <video/omapvrfb.h> - -#include "omapfb.h" - -#define MODULE_NAME "omapfb" - -#define OMAPFB_PLANE_XRES_MIN 8 -#define OMAPFB_PLANE_YRES_MIN 8 - -static char *def_mode; -static char *def_vram; -static bool def_vrfb; -static int def_rotate; -static bool def_mirror; -static bool auto_update; -static unsigned int auto_update_freq; -module_param(auto_update, bool, 0); -module_param(auto_update_freq, uint, 0644); - -#ifdef DEBUG -bool omapfb_debug; -module_param_named(debug, omapfb_debug, bool, 0644); -static bool omapfb_test_pattern; -module_param_named(test, omapfb_test_pattern, bool, 0644); -#endif - -static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi); -static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev, - struct omap_dss_device *dssdev); - -#ifdef DEBUG -static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color) -{ - struct fb_var_screeninfo *var = &fbi->var; - struct fb_fix_screeninfo *fix = &fbi->fix; - void __iomem *addr = fbi->screen_base; - const unsigned bytespp = var->bits_per_pixel >> 3; - const unsigned line_len = fix->line_length / bytespp; - - int r = (color >> 16) & 0xff; - int g = (color >> 8) & 0xff; - int b = (color >> 0) & 0xff; - - if (var->bits_per_pixel == 16) { - u16 __iomem *p = (u16 __iomem *)addr; - p += y * line_len + x; - - r = r * 32 / 256; - g = g * 64 / 256; - b = b * 32 / 256; - - __raw_writew((r << 11) | (g << 5) | (b << 0), p); - } else if (var->bits_per_pixel == 24) { - u8 __iomem *p = (u8 __iomem *)addr; - p += (y * line_len + x) * 3; - - __raw_writeb(b, p + 0); - __raw_writeb(g, p + 1); - __raw_writeb(r, p + 2); - } else if (var->bits_per_pixel == 32) { - u32 __iomem *p = (u32 __iomem *)addr; - p += y * line_len + x; - __raw_writel(color, p); - } -} - -static void fill_fb(struct fb_info *fbi) -{ - struct fb_var_screeninfo *var = &fbi->var; - const short w = var->xres_virtual; - const short h = var->yres_virtual; - void __iomem *addr = fbi->screen_base; - int y, x; - - if (!addr) - return; - - DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length); - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - if (x < 20 && y < 20) - draw_pixel(fbi, x, y, 0xffffff); - else if (x < 20 && (y > 20 && y < h - 20)) - draw_pixel(fbi, x, y, 0xff); - else if (y < 20 && (x > 20 && x < w - 20)) - draw_pixel(fbi, x, y, 0xff00); - else if (x > w - 20 && (y > 20 && y < h - 20)) - draw_pixel(fbi, x, y, 0xff0000); - else if (y > h - 20 && (x > 20 && x < w - 20)) - draw_pixel(fbi, x, y, 0xffff00); - else if (x == 20 || x == w - 20 || - y == 20 || y == h - 20) - draw_pixel(fbi, x, y, 0xffffff); - else if (x == y || w - x == h - y) - draw_pixel(fbi, x, y, 0xff00ff); - else if (w - x == y || x == h - y) - draw_pixel(fbi, x, y, 0x00ffff); - else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) { - int t = x * 3 / w; - unsigned r = 0, g = 0, b = 0; - unsigned c; - if (var->bits_per_pixel == 16) { - if (t == 0) - b = (y % 32) * 256 / 32; - else if (t == 1) - g = (y % 64) * 256 / 64; - else if (t == 2) - r = (y % 32) * 256 / 32; - } else { - if (t == 0) - b = (y % 256); - else if (t == 1) - g = (y % 256); - else if (t == 2) - r = (y % 256); - } - c = (r << 16) | (g << 8) | (b << 0); - draw_pixel(fbi, x, y, c); - } else { - draw_pixel(fbi, x, y, 0); - } - } - } -} -#endif - -static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) -{ - const struct vrfb *vrfb = &ofbi->region->vrfb; - unsigned offset; - - switch (rot) { - case FB_ROTATE_UR: - offset = 0; - break; - case FB_ROTATE_CW: - offset = vrfb->yoffset; - break; - case FB_ROTATE_UD: - offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset; - break; - case FB_ROTATE_CCW: - offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN; - break; - default: - BUG(); - return 0; - } - - offset *= vrfb->bytespp; - - return offset; -} - -static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot) -{ - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { - return ofbi->region->vrfb.paddr[rot] - + omapfb_get_vrfb_offset(ofbi, rot); - } else { - return ofbi->region->paddr; - } -} - -static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi) -{ - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) - return ofbi->region->vrfb.paddr[0]; - else - return ofbi->region->paddr; -} - -static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi) -{ - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) - return ofbi->region->vrfb.vaddr[0]; - else - return ofbi->region->vaddr; -} - -static struct omapfb_colormode omapfb_colormodes[] = { - { - .dssmode = OMAP_DSS_COLOR_UYVY, - .bits_per_pixel = 16, - .nonstd = OMAPFB_COLOR_YUV422, - }, { - .dssmode = OMAP_DSS_COLOR_YUV2, - .bits_per_pixel = 16, - .nonstd = OMAPFB_COLOR_YUY422, - }, { - .dssmode = OMAP_DSS_COLOR_ARGB16, - .bits_per_pixel = 16, - .red = { .length = 4, .offset = 8, .msb_right = 0 }, - .green = { .length = 4, .offset = 4, .msb_right = 0 }, - .blue = { .length = 4, .offset = 0, .msb_right = 0 }, - .transp = { .length = 4, .offset = 12, .msb_right = 0 }, - }, { - .dssmode = OMAP_DSS_COLOR_RGB16, - .bits_per_pixel = 16, - .red = { .length = 5, .offset = 11, .msb_right = 0 }, - .green = { .length = 6, .offset = 5, .msb_right = 0 }, - .blue = { .length = 5, .offset = 0, .msb_right = 0 }, - .transp = { .length = 0, .offset = 0, .msb_right = 0 }, - }, { - .dssmode = OMAP_DSS_COLOR_RGB24P, - .bits_per_pixel = 24, - .red = { .length = 8, .offset = 16, .msb_right = 0 }, - .green = { .length = 8, .offset = 8, .msb_right = 0 }, - .blue = { .length = 8, .offset = 0, .msb_right = 0 }, - .transp = { .length = 0, .offset = 0, .msb_right = 0 }, - }, { - .dssmode = OMAP_DSS_COLOR_RGB24U, - .bits_per_pixel = 32, - .red = { .length = 8, .offset = 16, .msb_right = 0 }, - .green = { .length = 8, .offset = 8, .msb_right = 0 }, - .blue = { .length = 8, .offset = 0, .msb_right = 0 }, - .transp = { .length = 0, .offset = 0, .msb_right = 0 }, - }, { - .dssmode = OMAP_DSS_COLOR_ARGB32, - .bits_per_pixel = 32, - .red = { .length = 8, .offset = 16, .msb_right = 0 }, - .green = { .length = 8, .offset = 8, .msb_right = 0 }, - .blue = { .length = 8, .offset = 0, .msb_right = 0 }, - .transp = { .length = 8, .offset = 24, .msb_right = 0 }, - }, { - .dssmode = OMAP_DSS_COLOR_RGBA32, - .bits_per_pixel = 32, - .red = { .length = 8, .offset = 24, .msb_right = 0 }, - .green = { .length = 8, .offset = 16, .msb_right = 0 }, - .blue = { .length = 8, .offset = 8, .msb_right = 0 }, - .transp = { .length = 8, .offset = 0, .msb_right = 0 }, - }, { - .dssmode = OMAP_DSS_COLOR_RGBX32, - .bits_per_pixel = 32, - .red = { .length = 8, .offset = 24, .msb_right = 0 }, - .green = { .length = 8, .offset = 16, .msb_right = 0 }, - .blue = { .length = 8, .offset = 8, .msb_right = 0 }, - .transp = { .length = 0, .offset = 0, .msb_right = 0 }, - }, -}; - -static bool cmp_var_to_colormode(struct fb_var_screeninfo *var, - struct omapfb_colormode *color) -{ - bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2) - { - return f1->length == f2->length && - f1->offset == f2->offset && - f1->msb_right == f2->msb_right; - } - - if (var->bits_per_pixel == 0 || - var->red.length == 0 || - var->blue.length == 0 || - var->green.length == 0) - return 0; - - return var->bits_per_pixel == color->bits_per_pixel && - cmp_component(&var->red, &color->red) && - cmp_component(&var->green, &color->green) && - cmp_component(&var->blue, &color->blue) && - cmp_component(&var->transp, &color->transp); -} - -static void assign_colormode_to_var(struct fb_var_screeninfo *var, - struct omapfb_colormode *color) -{ - var->bits_per_pixel = color->bits_per_pixel; - var->nonstd = color->nonstd; - var->red = color->red; - var->green = color->green; - var->blue = color->blue; - var->transp = color->transp; -} - -static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var, - enum omap_color_mode *mode) -{ - enum omap_color_mode dssmode; - int i; - - /* first match with nonstd field */ - if (var->nonstd) { - for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { - struct omapfb_colormode *m = &omapfb_colormodes[i]; - if (var->nonstd == m->nonstd) { - assign_colormode_to_var(var, m); - *mode = m->dssmode; - return 0; - } - } - - return -EINVAL; - } - - /* then try exact match of bpp and colors */ - for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { - struct omapfb_colormode *m = &omapfb_colormodes[i]; - if (cmp_var_to_colormode(var, m)) { - assign_colormode_to_var(var, m); - *mode = m->dssmode; - return 0; - } - } - - /* match with bpp if user has not filled color fields - * properly */ - switch (var->bits_per_pixel) { - case 1: - dssmode = OMAP_DSS_COLOR_CLUT1; - break; - case 2: - dssmode = OMAP_DSS_COLOR_CLUT2; - break; - case 4: - dssmode = OMAP_DSS_COLOR_CLUT4; - break; - case 8: - dssmode = OMAP_DSS_COLOR_CLUT8; - break; - case 12: - dssmode = OMAP_DSS_COLOR_RGB12U; - break; - case 16: - dssmode = OMAP_DSS_COLOR_RGB16; - break; - case 24: - dssmode = OMAP_DSS_COLOR_RGB24P; - break; - case 32: - dssmode = OMAP_DSS_COLOR_RGB24U; - break; - default: - return -EINVAL; - } - - for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { - struct omapfb_colormode *m = &omapfb_colormodes[i]; - if (dssmode == m->dssmode) { - assign_colormode_to_var(var, m); - *mode = m->dssmode; - return 0; - } - } - - return -EINVAL; -} - -static int check_fb_res_bounds(struct fb_var_screeninfo *var) -{ - int xres_min = OMAPFB_PLANE_XRES_MIN; - int xres_max = 2048; - int yres_min = OMAPFB_PLANE_YRES_MIN; - int yres_max = 2048; - - /* XXX: some applications seem to set virtual res to 0. */ - if (var->xres_virtual == 0) - var->xres_virtual = var->xres; - - if (var->yres_virtual == 0) - var->yres_virtual = var->yres; - - if (var->xres_virtual < xres_min || var->yres_virtual < yres_min) - return -EINVAL; - - if (var->xres < xres_min) - var->xres = xres_min; - if (var->yres < yres_min) - var->yres = yres_min; - if (var->xres > xres_max) - var->xres = xres_max; - if (var->yres > yres_max) - var->yres = yres_max; - - if (var->xres > var->xres_virtual) - var->xres = var->xres_virtual; - if (var->yres > var->yres_virtual) - var->yres = var->yres_virtual; - - return 0; -} - -static void shrink_height(unsigned long max_frame_size, - struct fb_var_screeninfo *var) -{ - DBG("can't fit FB into memory, reducing y\n"); - var->yres_virtual = max_frame_size / - (var->xres_virtual * var->bits_per_pixel >> 3); - - if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN) - var->yres_virtual = OMAPFB_PLANE_YRES_MIN; - - if (var->yres > var->yres_virtual) - var->yres = var->yres_virtual; -} - -static void shrink_width(unsigned long max_frame_size, - struct fb_var_screeninfo *var) -{ - DBG("can't fit FB into memory, reducing x\n"); - var->xres_virtual = max_frame_size / var->yres_virtual / - (var->bits_per_pixel >> 3); - - if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN) - var->xres_virtual = OMAPFB_PLANE_XRES_MIN; - - if (var->xres > var->xres_virtual) - var->xres = var->xres_virtual; -} - -static int check_vrfb_fb_size(unsigned long region_size, - const struct fb_var_screeninfo *var) -{ - unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual, - var->yres_virtual, var->bits_per_pixel >> 3); - - return min_phys_size > region_size ? -EINVAL : 0; -} - -static int check_fb_size(const struct omapfb_info *ofbi, - struct fb_var_screeninfo *var) -{ - unsigned long max_frame_size = ofbi->region->size; - int bytespp = var->bits_per_pixel >> 3; - unsigned long line_size = var->xres_virtual * bytespp; - - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { - /* One needs to check for both VRFB and OMAPFB limitations. */ - if (check_vrfb_fb_size(max_frame_size, var)) - shrink_height(omap_vrfb_max_height( - max_frame_size, var->xres_virtual, bytespp) * - line_size, var); - - if (check_vrfb_fb_size(max_frame_size, var)) { - DBG("cannot fit FB to memory\n"); - return -EINVAL; - } - - return 0; - } - - DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size); - - if (line_size * var->yres_virtual > max_frame_size) - shrink_height(max_frame_size, var); - - if (line_size * var->yres_virtual > max_frame_size) { - shrink_width(max_frame_size, var); - line_size = var->xres_virtual * bytespp; - } - - if (line_size * var->yres_virtual > max_frame_size) { - DBG("cannot fit FB to memory\n"); - return -EINVAL; - } - - return 0; -} - -/* - * Consider if VRFB assisted rotation is in use and if the virtual space for - * the zero degree view needs to be mapped. The need for mapping also acts as - * the trigger for setting up the hardware on the context in question. This - * ensures that one does not attempt to access the virtual view before the - * hardware is serving the address translations. - */ -static int setup_vrfb_rotation(struct fb_info *fbi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_mem_region *rg = ofbi->region; - struct vrfb *vrfb = &rg->vrfb; - struct fb_var_screeninfo *var = &fbi->var; - struct fb_fix_screeninfo *fix = &fbi->fix; - unsigned bytespp; - bool yuv_mode; - enum omap_color_mode mode; - int r; - bool reconf; - - if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB) - return 0; - - DBG("setup_vrfb_rotation\n"); - - r = fb_mode_to_dss_mode(var, &mode); - if (r) - return r; - - bytespp = var->bits_per_pixel >> 3; - - yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY; - - /* We need to reconfigure VRFB if the resolution changes, if yuv mode - * is enabled/disabled, or if bytes per pixel changes */ - - /* XXX we shouldn't allow this when framebuffer is mmapped */ - - reconf = false; - - if (yuv_mode != vrfb->yuv_mode) - reconf = true; - else if (bytespp != vrfb->bytespp) - reconf = true; - else if (vrfb->xres != var->xres_virtual || - vrfb->yres != var->yres_virtual) - reconf = true; - - if (vrfb->vaddr[0] && reconf) { - fbi->screen_base = NULL; - fix->smem_start = 0; - fix->smem_len = 0; - iounmap(vrfb->vaddr[0]); - vrfb->vaddr[0] = NULL; - DBG("setup_vrfb_rotation: reset fb\n"); - } - - if (vrfb->vaddr[0]) - return 0; - - omap_vrfb_setup(&rg->vrfb, rg->paddr, - var->xres_virtual, - var->yres_virtual, - bytespp, yuv_mode); - - /* Now one can ioremap the 0 angle view */ - r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0); - if (r) - return r; - - /* used by open/write in fbmem.c */ - fbi->screen_base = ofbi->region->vrfb.vaddr[0]; - - fix->smem_start = ofbi->region->vrfb.paddr[0]; - - switch (var->nonstd) { - case OMAPFB_COLOR_YUV422: - case OMAPFB_COLOR_YUY422: - fix->line_length = - (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2; - break; - default: - fix->line_length = - (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3; - break; - } - - fix->smem_len = var->yres_virtual * fix->line_length; - - return 0; -} - -int dss_mode_to_fb_mode(enum omap_color_mode dssmode, - struct fb_var_screeninfo *var) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { - struct omapfb_colormode *mode = &omapfb_colormodes[i]; - if (dssmode == mode->dssmode) { - assign_colormode_to_var(var, mode); - return 0; - } - } - return -ENOENT; -} - -void set_fb_fix(struct fb_info *fbi) -{ - struct fb_fix_screeninfo *fix = &fbi->fix; - struct fb_var_screeninfo *var = &fbi->var; - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_mem_region *rg = ofbi->region; - - DBG("set_fb_fix\n"); - - /* used by open/write in fbmem.c */ - fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi); - - /* used by mmap in fbmem.c */ - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { - switch (var->nonstd) { - case OMAPFB_COLOR_YUV422: - case OMAPFB_COLOR_YUY422: - fix->line_length = - (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2; - break; - default: - fix->line_length = - (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3; - break; - } - - fix->smem_len = var->yres_virtual * fix->line_length; - } else { - fix->line_length = - (var->xres_virtual * var->bits_per_pixel) >> 3; - fix->smem_len = rg->size; - } - - fix->smem_start = omapfb_get_region_paddr(ofbi); - - fix->type = FB_TYPE_PACKED_PIXELS; - - if (var->nonstd) - fix->visual = FB_VISUAL_PSEUDOCOLOR; - else { - switch (var->bits_per_pixel) { - case 32: - case 24: - case 16: - case 12: - fix->visual = FB_VISUAL_TRUECOLOR; - /* 12bpp is stored in 16 bits */ - break; - case 1: - case 2: - case 4: - case 8: - fix->visual = FB_VISUAL_PSEUDOCOLOR; - break; - } - } - - fix->accel = FB_ACCEL_NONE; - - fix->xpanstep = 1; - fix->ypanstep = 1; -} - -/* check new var and possibly modify it to be ok */ -int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omap_dss_device *display = fb2display(fbi); - enum omap_color_mode mode = 0; - int i; - int r; - - DBG("check_fb_var %d\n", ofbi->id); - - WARN_ON(!atomic_read(&ofbi->region->lock_count)); - - r = fb_mode_to_dss_mode(var, &mode); - if (r) { - DBG("cannot convert var to omap dss mode\n"); - return r; - } - - for (i = 0; i < ofbi->num_overlays; ++i) { - if ((ofbi->overlays[i]->supported_modes & mode) == 0) { - DBG("invalid mode\n"); - return -EINVAL; - } - } - - if (var->rotate > 3) - return -EINVAL; - - if (check_fb_res_bounds(var)) - return -EINVAL; - - /* When no memory is allocated ignore the size check */ - if (ofbi->region->size != 0 && check_fb_size(ofbi, var)) - return -EINVAL; - - if (var->xres + var->xoffset > var->xres_virtual) - var->xoffset = var->xres_virtual - var->xres; - if (var->yres + var->yoffset > var->yres_virtual) - var->yoffset = var->yres_virtual - var->yres; - - DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n", - var->xres, var->yres, - var->xres_virtual, var->yres_virtual); - - if (display && display->driver->get_dimensions) { - u32 w, h; - display->driver->get_dimensions(display, &w, &h); - var->width = DIV_ROUND_CLOSEST(w, 1000); - var->height = DIV_ROUND_CLOSEST(h, 1000); - } else { - var->height = -1; - var->width = -1; - } - - var->grayscale = 0; - - if (display && display->driver->get_timings) { - struct omap_video_timings timings; - display->driver->get_timings(display, &timings); - - /* pixclock in ps, the rest in pixclock */ - var->pixclock = timings.pixelclock != 0 ? - KHZ2PICOS(timings.pixelclock / 1000) : - 0; - var->left_margin = timings.hbp; - var->right_margin = timings.hfp; - var->upper_margin = timings.vbp; - var->lower_margin = timings.vfp; - var->hsync_len = timings.hsw; - var->vsync_len = timings.vsw; - var->sync |= timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH ? - FB_SYNC_HOR_HIGH_ACT : 0; - var->sync |= timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH ? - FB_SYNC_VERT_HIGH_ACT : 0; - var->vmode = timings.interlace ? - FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED; - } else { - var->pixclock = 0; - var->left_margin = 0; - var->right_margin = 0; - var->upper_margin = 0; - var->lower_margin = 0; - var->hsync_len = 0; - var->vsync_len = 0; - var->sync = 0; - var->vmode = FB_VMODE_NONINTERLACED; - } - - return 0; -} - -/* - * --------------------------------------------------------------------------- - * fbdev framework callbacks - * --------------------------------------------------------------------------- - */ -static int omapfb_open(struct fb_info *fbi, int user) -{ - return 0; -} - -static int omapfb_release(struct fb_info *fbi, int user) -{ - return 0; -} - -static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var, - const struct fb_fix_screeninfo *fix, int rotation) -{ - unsigned offset; - - offset = var->yoffset * fix->line_length + - var->xoffset * (var->bits_per_pixel >> 3); - - return offset; -} - -static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var, - const struct fb_fix_screeninfo *fix, int rotation) -{ - unsigned offset; - - if (rotation == FB_ROTATE_UD) - offset = (var->yres_virtual - var->yres) * - fix->line_length; - else if (rotation == FB_ROTATE_CW) - offset = (var->yres_virtual - var->yres) * - (var->bits_per_pixel >> 3); - else - offset = 0; - - if (rotation == FB_ROTATE_UR) - offset += var->yoffset * fix->line_length + - var->xoffset * (var->bits_per_pixel >> 3); - else if (rotation == FB_ROTATE_UD) - offset -= var->yoffset * fix->line_length + - var->xoffset * (var->bits_per_pixel >> 3); - else if (rotation == FB_ROTATE_CW) - offset -= var->xoffset * fix->line_length + - var->yoffset * (var->bits_per_pixel >> 3); - else if (rotation == FB_ROTATE_CCW) - offset += var->xoffset * fix->line_length + - var->yoffset * (var->bits_per_pixel >> 3); - - return offset; -} - -static void omapfb_calc_addr(const struct omapfb_info *ofbi, - const struct fb_var_screeninfo *var, - const struct fb_fix_screeninfo *fix, - int rotation, u32 *paddr) -{ - u32 data_start_p; - int offset; - - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) - data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); - else - data_start_p = omapfb_get_region_paddr(ofbi); - - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) - offset = calc_rotation_offset_vrfb(var, fix, rotation); - else - offset = calc_rotation_offset_dma(var, fix, rotation); - - data_start_p += offset; - - if (offset) - DBG("offset %d, %d = %d\n", - var->xoffset, var->yoffset, offset); - - DBG("paddr %x\n", data_start_p); - - *paddr = data_start_p; -} - -/* setup overlay according to the fb */ -int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, - u16 posx, u16 posy, u16 outw, u16 outh) -{ - int r = 0; - struct omapfb_info *ofbi = FB2OFB(fbi); - struct fb_var_screeninfo *var = &fbi->var; - struct fb_fix_screeninfo *fix = &fbi->fix; - enum omap_color_mode mode = 0; - u32 data_start_p = 0; - struct omap_overlay_info info; - int xres, yres; - int screen_width; - int mirror; - int rotation = var->rotate; - int i; - - WARN_ON(!atomic_read(&ofbi->region->lock_count)); - - for (i = 0; i < ofbi->num_overlays; i++) { - if (ovl != ofbi->overlays[i]) - continue; - - rotation = (rotation + ofbi->rotation[i]) % 4; - break; - } - - DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id, - posx, posy, outw, outh); - - if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) { - xres = var->yres; - yres = var->xres; - } else { - xres = var->xres; - yres = var->yres; - } - - if (ofbi->region->size) - omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p); - - r = fb_mode_to_dss_mode(var, &mode); - if (r) { - DBG("fb_mode_to_dss_mode failed"); - goto err; - } - - switch (var->nonstd) { - case OMAPFB_COLOR_YUV422: - case OMAPFB_COLOR_YUY422: - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { - screen_width = fix->line_length - / (var->bits_per_pixel >> 2); - break; - } - default: - screen_width = fix->line_length / (var->bits_per_pixel >> 3); - break; - } - - ovl->get_overlay_info(ovl, &info); - - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) - mirror = 0; - else - mirror = ofbi->mirror; - - info.paddr = data_start_p; - info.screen_width = screen_width; - info.width = xres; - info.height = yres; - info.color_mode = mode; - info.rotation_type = ofbi->rotation_type; - info.rotation = rotation; - info.mirror = mirror; - - info.pos_x = posx; - info.pos_y = posy; - info.out_width = outw; - info.out_height = outh; - - r = ovl->set_overlay_info(ovl, &info); - if (r) { - DBG("ovl->setup_overlay_info failed\n"); - goto err; - } - - return 0; - -err: - DBG("setup_overlay failed\n"); - return r; -} - -/* apply var to the overlay */ -int omapfb_apply_changes(struct fb_info *fbi, int init) -{ - int r = 0; - struct omapfb_info *ofbi = FB2OFB(fbi); - struct fb_var_screeninfo *var = &fbi->var; - struct omap_overlay *ovl; - u16 posx, posy; - u16 outw, outh; - int i; - -#ifdef DEBUG - if (omapfb_test_pattern) - fill_fb(fbi); -#endif - - WARN_ON(!atomic_read(&ofbi->region->lock_count)); - - for (i = 0; i < ofbi->num_overlays; i++) { - ovl = ofbi->overlays[i]; - - DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); - - if (ofbi->region->size == 0) { - /* the fb is not available. disable the overlay */ - omapfb_overlay_enable(ovl, 0); - if (!init && ovl->manager) - ovl->manager->apply(ovl->manager); - continue; - } - - if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { - int rotation = (var->rotate + ofbi->rotation[i]) % 4; - if (rotation == FB_ROTATE_CW || - rotation == FB_ROTATE_CCW) { - outw = var->yres; - outh = var->xres; - } else { - outw = var->xres; - outh = var->yres; - } - } else { - struct omap_overlay_info info; - ovl->get_overlay_info(ovl, &info); - outw = info.out_width; - outh = info.out_height; - } - - if (init) { - posx = 0; - posy = 0; - } else { - struct omap_overlay_info info; - ovl->get_overlay_info(ovl, &info); - posx = info.pos_x; - posy = info.pos_y; - } - - r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh); - if (r) - goto err; - - if (!init && ovl->manager) - ovl->manager->apply(ovl->manager); - } - return 0; -err: - DBG("apply_changes failed\n"); - return r; -} - -/* checks var and eventually tweaks it to something supported, - * DO NOT MODIFY PAR */ -static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - int r; - - DBG("check_var(%d)\n", FB2OFB(fbi)->id); - - omapfb_get_mem_region(ofbi->region); - - r = check_fb_var(fbi, var); - - omapfb_put_mem_region(ofbi->region); - - return r; -} - -/* set the video mode according to info->var */ -static int omapfb_set_par(struct fb_info *fbi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - int r; - - DBG("set_par(%d)\n", FB2OFB(fbi)->id); - - omapfb_get_mem_region(ofbi->region); - - set_fb_fix(fbi); - - r = setup_vrfb_rotation(fbi); - if (r) - goto out; - - r = omapfb_apply_changes(fbi, 0); - - out: - omapfb_put_mem_region(ofbi->region); - - return r; -} - -static int omapfb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *fbi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct fb_var_screeninfo new_var; - int r; - - DBG("pan_display(%d)\n", FB2OFB(fbi)->id); - - if (var->xoffset == fbi->var.xoffset && - var->yoffset == fbi->var.yoffset) - return 0; - - new_var = fbi->var; - new_var.xoffset = var->xoffset; - new_var.yoffset = var->yoffset; - - fbi->var = new_var; - - omapfb_get_mem_region(ofbi->region); - - r = omapfb_apply_changes(fbi, 0); - - omapfb_put_mem_region(ofbi->region); - - return r; -} - -static void mmap_user_open(struct vm_area_struct *vma) -{ - struct omapfb2_mem_region *rg = vma->vm_private_data; - - omapfb_get_mem_region(rg); - atomic_inc(&rg->map_count); - omapfb_put_mem_region(rg); -} - -static void mmap_user_close(struct vm_area_struct *vma) -{ - struct omapfb2_mem_region *rg = vma->vm_private_data; - - omapfb_get_mem_region(rg); - atomic_dec(&rg->map_count); - omapfb_put_mem_region(rg); -} - -static struct vm_operations_struct mmap_user_ops = { - .open = mmap_user_open, - .close = mmap_user_close, -}; - -static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct fb_fix_screeninfo *fix = &fbi->fix; - struct omapfb2_mem_region *rg; - unsigned long start; - u32 len; - int r; - - rg = omapfb_get_mem_region(ofbi->region); - - start = omapfb_get_region_paddr(ofbi); - len = fix->smem_len; - - DBG("user mmap region start %lx, len %d, off %lx\n", start, len, - vma->vm_pgoff << PAGE_SHIFT); - - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - vma->vm_ops = &mmap_user_ops; - vma->vm_private_data = rg; - - r = vm_iomap_memory(vma, start, len); - if (r) - goto error; - - /* vm_ops.open won't be called for mmap itself. */ - atomic_inc(&rg->map_count); - - omapfb_put_mem_region(rg); - - return 0; - -error: - omapfb_put_mem_region(ofbi->region); - - return r; -} - -/* Store a single color palette entry into a pseudo palette or the hardware - * palette if one is available. For now we support only 16bpp and thus store - * the entry only to the pseudo palette. - */ -static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, - u_int blue, u_int transp, int update_hw_pal) -{ - /*struct omapfb_info *ofbi = FB2OFB(fbi);*/ - /*struct omapfb2_device *fbdev = ofbi->fbdev;*/ - struct fb_var_screeninfo *var = &fbi->var; - int r = 0; - - enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */ - - /*switch (plane->color_mode) {*/ - switch (mode) { - case OMAPFB_COLOR_YUV422: - case OMAPFB_COLOR_YUV420: - case OMAPFB_COLOR_YUY422: - r = -EINVAL; - break; - case OMAPFB_COLOR_CLUT_8BPP: - case OMAPFB_COLOR_CLUT_4BPP: - case OMAPFB_COLOR_CLUT_2BPP: - case OMAPFB_COLOR_CLUT_1BPP: - /* - if (fbdev->ctrl->setcolreg) - r = fbdev->ctrl->setcolreg(regno, red, green, blue, - transp, update_hw_pal); - */ - /* Fallthrough */ - r = -EINVAL; - break; - case OMAPFB_COLOR_RGB565: - case OMAPFB_COLOR_RGB444: - case OMAPFB_COLOR_RGB24P: - case OMAPFB_COLOR_RGB24U: - if (r != 0) - break; - - if (regno < 16) { - u32 pal; - pal = ((red >> (16 - var->red.length)) << - var->red.offset) | - ((green >> (16 - var->green.length)) << - var->green.offset) | - (blue >> (16 - var->blue.length)); - ((u32 *)(fbi->pseudo_palette))[regno] = pal; - } - break; - default: - BUG(); - } - return r; -} - -static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info) -{ - DBG("setcolreg\n"); - - return _setcolreg(info, regno, red, green, blue, transp, 1); -} - -static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) -{ - int count, index, r; - u16 *red, *green, *blue, *transp; - u16 trans = 0xffff; - - DBG("setcmap\n"); - - red = cmap->red; - green = cmap->green; - blue = cmap->blue; - transp = cmap->transp; - index = cmap->start; - - for (count = 0; count < cmap->len; count++) { - if (transp) - trans = *transp++; - r = _setcolreg(info, index++, *red++, *green++, *blue++, trans, - count == cmap->len - 1); - if (r != 0) - return r; - } - - return 0; -} - -static int omapfb_blank(int blank, struct fb_info *fbi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omap_dss_device *display = fb2display(fbi); - struct omapfb_display_data *d; - int r = 0; - - if (!display) - return -EINVAL; - - omapfb_lock(fbdev); - - d = get_display_data(fbdev, display); - - switch (blank) { - case FB_BLANK_UNBLANK: - if (display->state == OMAP_DSS_DISPLAY_ACTIVE) - goto exit; - - r = display->driver->enable(display); - - if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) && - d->update_mode == OMAPFB_AUTO_UPDATE && - !d->auto_update_work_enabled) - omapfb_start_auto_update(fbdev, display); - - break; - - case FB_BLANK_NORMAL: - /* FB_BLANK_NORMAL could be implemented. - * Needs DSS additions. */ - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (display->state != OMAP_DSS_DISPLAY_ACTIVE) - goto exit; - - if (d->auto_update_work_enabled) - omapfb_stop_auto_update(fbdev, display); - - display->driver->disable(display); - - break; - - default: - r = -EINVAL; - } - -exit: - omapfb_unlock(fbdev); - - return r; -} - -#if 0 -/* XXX fb_read and fb_write are needed for VRFB */ -ssize_t omapfb_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos); - /* XXX needed for VRFB */ - return count; -} -#endif - -static struct fb_ops omapfb_ops = { - .owner = THIS_MODULE, - .fb_open = omapfb_open, - .fb_release = omapfb_release, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_blank = omapfb_blank, - .fb_ioctl = omapfb_ioctl, - .fb_check_var = omapfb_check_var, - .fb_set_par = omapfb_set_par, - .fb_pan_display = omapfb_pan_display, - .fb_mmap = omapfb_mmap, - .fb_setcolreg = omapfb_setcolreg, - .fb_setcmap = omapfb_setcmap, - /*.fb_write = omapfb_write,*/ -}; - -static void omapfb_free_fbmem(struct fb_info *fbi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omapfb2_mem_region *rg; - - rg = ofbi->region; - - if (rg->token == NULL) - return; - - WARN_ON(atomic_read(&rg->map_count)); - - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { - /* unmap the 0 angle rotation */ - if (rg->vrfb.vaddr[0]) { - iounmap(rg->vrfb.vaddr[0]); - rg->vrfb.vaddr[0] = NULL; - } - - omap_vrfb_release_ctx(&rg->vrfb); - } - - dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle, - &rg->attrs); - - rg->token = NULL; - rg->vaddr = NULL; - rg->paddr = 0; - rg->alloc = 0; - rg->size = 0; -} - -static void clear_fb_info(struct fb_info *fbi) -{ - memset(&fbi->var, 0, sizeof(fbi->var)); - memset(&fbi->fix, 0, sizeof(fbi->fix)); - strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id)); -} - -static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev) -{ - int i; - - DBG("free all fbmem\n"); - - for (i = 0; i < fbdev->num_fbs; i++) { - struct fb_info *fbi = fbdev->fbs[i]; - omapfb_free_fbmem(fbi); - clear_fb_info(fbi); - } - - return 0; -} - -static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, - unsigned long paddr) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omapfb2_mem_region *rg; - void *token; - DEFINE_DMA_ATTRS(attrs); - dma_addr_t dma_handle; - int r; - - rg = ofbi->region; - - rg->paddr = 0; - rg->vaddr = NULL; - memset(&rg->vrfb, 0, sizeof rg->vrfb); - rg->size = 0; - rg->type = 0; - rg->alloc = false; - rg->map = false; - - size = PAGE_ALIGN(size); - - dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); - - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) - dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); - - DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); - - token = dma_alloc_attrs(fbdev->dev, size, &dma_handle, - GFP_KERNEL, &attrs); - - if (token == NULL) { - dev_err(fbdev->dev, "failed to allocate framebuffer\n"); - return -ENOMEM; - } - - DBG("allocated VRAM paddr %lx, vaddr %p\n", - (unsigned long)dma_handle, token); - - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { - r = omap_vrfb_request_ctx(&rg->vrfb); - if (r) { - dma_free_attrs(fbdev->dev, size, token, dma_handle, - &attrs); - dev_err(fbdev->dev, "vrfb create ctx failed\n"); - return r; - } - } - - rg->attrs = attrs; - rg->token = token; - rg->dma_handle = dma_handle; - - rg->paddr = (unsigned long)dma_handle; - rg->vaddr = (void __iomem *)token; - rg->size = size; - rg->alloc = 1; - - return 0; -} - -/* allocate fbmem using display resolution as reference */ -static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size, - unsigned long paddr) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omap_dss_device *display; - int bytespp; - - display = fb2display(fbi); - - if (!display) - return 0; - - switch (omapfb_get_recommended_bpp(fbdev, display)) { - case 16: - bytespp = 2; - break; - case 24: - bytespp = 4; - break; - default: - bytespp = 4; - break; - } - - if (!size) { - u16 w, h; - - display->driver->get_resolution(display, &w, &h); - - if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { - size = max(omap_vrfb_min_phys_size(w, h, bytespp), - omap_vrfb_min_phys_size(h, w, bytespp)); - - DBG("adjusting fb mem size for VRFB, %u -> %lu\n", - w * h * bytespp, size); - } else { - size = w * h * bytespp; - } - } - - if (!size) - return 0; - - return omapfb_alloc_fbmem(fbi, size, paddr); -} - -static int omapfb_parse_vram_param(const char *param, int max_entries, - unsigned long *sizes, unsigned long *paddrs) -{ - int fbnum; - unsigned long size; - unsigned long paddr = 0; - char *p, *start; - - start = (char *)param; - - while (1) { - p = start; - - fbnum = simple_strtoul(p, &p, 10); - - if (p == start) - return -EINVAL; - - if (*p != ':') - return -EINVAL; - - if (fbnum >= max_entries) - return -EINVAL; - - size = memparse(p + 1, &p); - - if (!size) - return -EINVAL; - - paddr = 0; - - if (*p == '@') { - paddr = simple_strtoul(p + 1, &p, 16); - - if (!paddr) - return -EINVAL; - - } - - WARN_ONCE(paddr, - "reserving memory at predefined address not supported\n"); - - paddrs[fbnum] = paddr; - sizes[fbnum] = size; - - if (*p == 0) - break; - - if (*p != ',') - return -EINVAL; - - ++p; - - start = p; - } - - return 0; -} - -static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev) -{ - int i, r; - unsigned long vram_sizes[10]; - unsigned long vram_paddrs[10]; - - memset(&vram_sizes, 0, sizeof(vram_sizes)); - memset(&vram_paddrs, 0, sizeof(vram_paddrs)); - - if (def_vram && omapfb_parse_vram_param(def_vram, 10, - vram_sizes, vram_paddrs)) { - dev_err(fbdev->dev, "failed to parse vram parameter\n"); - - memset(&vram_sizes, 0, sizeof(vram_sizes)); - memset(&vram_paddrs, 0, sizeof(vram_paddrs)); - } - - for (i = 0; i < fbdev->num_fbs; i++) { - /* allocate memory automatically only for fb0, or if - * excplicitly defined with vram or plat data option */ - if (i == 0 || vram_sizes[i] != 0) { - r = omapfb_alloc_fbmem_display(fbdev->fbs[i], - vram_sizes[i], vram_paddrs[i]); - - if (r) - return r; - } - } - - for (i = 0; i < fbdev->num_fbs; i++) { - struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); - struct omapfb2_mem_region *rg; - rg = ofbi->region; - - DBG("region%d phys %08x virt %p size=%lu\n", - i, - rg->paddr, - rg->vaddr, - rg->size); - } - - return 0; -} - -static void omapfb_clear_fb(struct fb_info *fbi) -{ - const struct fb_fillrect rect = { - .dx = 0, - .dy = 0, - .width = fbi->var.xres_virtual, - .height = fbi->var.yres_virtual, - .color = 0, - .rop = ROP_COPY, - }; - - cfb_fillrect(fbi, &rect); -} - -int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omapfb2_mem_region *rg = ofbi->region; - unsigned long old_size = rg->size; - unsigned long old_paddr = rg->paddr; - int old_type = rg->type; - int r; - - if (type != OMAPFB_MEMTYPE_SDRAM) - return -EINVAL; - - size = PAGE_ALIGN(size); - - if (old_size == size && old_type == type) - return 0; - - omapfb_free_fbmem(fbi); - - if (size == 0) { - clear_fb_info(fbi); - return 0; - } - - r = omapfb_alloc_fbmem(fbi, size, 0); - - if (r) { - if (old_size) - omapfb_alloc_fbmem(fbi, old_size, old_paddr); - - if (rg->size == 0) - clear_fb_info(fbi); - - return r; - } - - if (old_size == size) - return 0; - - if (old_size == 0) { - DBG("initializing fb %d\n", ofbi->id); - r = omapfb_fb_init(fbdev, fbi); - if (r) { - DBG("omapfb_fb_init failed\n"); - goto err; - } - r = omapfb_apply_changes(fbi, 1); - if (r) { - DBG("omapfb_apply_changes failed\n"); - goto err; - } - } else { - struct fb_var_screeninfo new_var; - memcpy(&new_var, &fbi->var, sizeof(new_var)); - r = check_fb_var(fbi, &new_var); - if (r) - goto err; - memcpy(&fbi->var, &new_var, sizeof(fbi->var)); - set_fb_fix(fbi); - r = setup_vrfb_rotation(fbi); - if (r) - goto err; - } - - omapfb_clear_fb(fbi); - - return 0; -err: - omapfb_free_fbmem(fbi); - clear_fb_info(fbi); - return r; -} - -static void omapfb_auto_update_work(struct work_struct *work) -{ - struct omap_dss_device *dssdev; - struct omap_dss_driver *dssdrv; - struct omapfb_display_data *d; - u16 w, h; - unsigned int freq; - struct omapfb2_device *fbdev; - - d = container_of(work, struct omapfb_display_data, - auto_update_work.work); - - dssdev = d->dssdev; - dssdrv = dssdev->driver; - fbdev = d->fbdev; - - if (!dssdrv || !dssdrv->update) - return; - - if (dssdrv->sync) - dssdrv->sync(dssdev); - - dssdrv->get_resolution(dssdev, &w, &h); - dssdrv->update(dssdev, 0, 0, w, h); - - freq = auto_update_freq; - if (freq == 0) - freq = 20; - queue_delayed_work(fbdev->auto_update_wq, - &d->auto_update_work, HZ / freq); -} - -void omapfb_start_auto_update(struct omapfb2_device *fbdev, - struct omap_dss_device *display) -{ - struct omapfb_display_data *d; - - if (fbdev->auto_update_wq == NULL) { - struct workqueue_struct *wq; - - wq = create_singlethread_workqueue("omapfb_auto_update"); - - if (wq == NULL) { - dev_err(fbdev->dev, "Failed to create workqueue for " - "auto-update\n"); - return; - } - - fbdev->auto_update_wq = wq; - } - - d = get_display_data(fbdev, display); - - INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work); - - d->auto_update_work_enabled = true; - - omapfb_auto_update_work(&d->auto_update_work.work); -} - -void omapfb_stop_auto_update(struct omapfb2_device *fbdev, - struct omap_dss_device *display) -{ - struct omapfb_display_data *d; - - d = get_display_data(fbdev, display); - - cancel_delayed_work_sync(&d->auto_update_work); - - d->auto_update_work_enabled = false; -} - -/* initialize fb_info, var, fix to something sane based on the display */ -static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) -{ - struct fb_var_screeninfo *var = &fbi->var; - struct omap_dss_device *display = fb2display(fbi); - struct omapfb_info *ofbi = FB2OFB(fbi); - int r = 0; - - fbi->fbops = &omapfb_ops; - fbi->flags = FBINFO_FLAG_DEFAULT; - fbi->pseudo_palette = fbdev->pseudo_palette; - - if (ofbi->region->size == 0) { - clear_fb_info(fbi); - return 0; - } - - var->nonstd = 0; - var->bits_per_pixel = 0; - - var->rotate = def_rotate; - - if (display) { - u16 w, h; - int rotation = (var->rotate + ofbi->rotation[0]) % 4; - - display->driver->get_resolution(display, &w, &h); - - if (rotation == FB_ROTATE_CW || - rotation == FB_ROTATE_CCW) { - var->xres = h; - var->yres = w; - } else { - var->xres = w; - var->yres = h; - } - - var->xres_virtual = var->xres; - var->yres_virtual = var->yres; - - if (!var->bits_per_pixel) { - switch (omapfb_get_recommended_bpp(fbdev, display)) { - case 16: - var->bits_per_pixel = 16; - break; - case 24: - var->bits_per_pixel = 32; - break; - default: - dev_err(fbdev->dev, "illegal display " - "bpp\n"); - return -EINVAL; - } - } - } else { - /* if there's no display, let's just guess some basic values */ - var->xres = 320; - var->yres = 240; - var->xres_virtual = var->xres; - var->yres_virtual = var->yres; - if (!var->bits_per_pixel) - var->bits_per_pixel = 16; - } - - r = check_fb_var(fbi, var); - if (r) - goto err; - - set_fb_fix(fbi); - r = setup_vrfb_rotation(fbi); - if (r) - goto err; - - r = fb_alloc_cmap(&fbi->cmap, 256, 0); - if (r) - dev_err(fbdev->dev, "unable to allocate color map memory\n"); - -err: - return r; -} - -static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi) -{ - fb_dealloc_cmap(&fbi->cmap); -} - - -static void omapfb_free_resources(struct omapfb2_device *fbdev) -{ - int i; - - DBG("free_resources\n"); - - if (fbdev == NULL) - return; - - for (i = 0; i < fbdev->num_fbs; i++) { - struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); - int j; - - for (j = 0; j < ofbi->num_overlays; j++) { - struct omap_overlay *ovl = ofbi->overlays[j]; - ovl->disable(ovl); - } - } - - for (i = 0; i < fbdev->num_fbs; i++) - unregister_framebuffer(fbdev->fbs[i]); - - /* free the reserved fbmem */ - omapfb_free_all_fbmem(fbdev); - - for (i = 0; i < fbdev->num_fbs; i++) { - fbinfo_cleanup(fbdev, fbdev->fbs[i]); - framebuffer_release(fbdev->fbs[i]); - } - - for (i = 0; i < fbdev->num_displays; i++) { - struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; - - if (fbdev->displays[i].auto_update_work_enabled) - omapfb_stop_auto_update(fbdev, dssdev); - - if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) - dssdev->driver->disable(dssdev); - - dssdev->driver->disconnect(dssdev); - - omap_dss_put_device(dssdev); - } - - if (fbdev->auto_update_wq != NULL) { - flush_workqueue(fbdev->auto_update_wq); - destroy_workqueue(fbdev->auto_update_wq); - fbdev->auto_update_wq = NULL; - } - - dev_set_drvdata(fbdev->dev, NULL); -} - -static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) -{ - int r, i; - - fbdev->num_fbs = 0; - - DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS); - - /* allocate fb_infos */ - for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) { - struct fb_info *fbi; - struct omapfb_info *ofbi; - - fbi = framebuffer_alloc(sizeof(struct omapfb_info), - fbdev->dev); - - if (fbi == NULL) { - dev_err(fbdev->dev, - "unable to allocate memory for plane info\n"); - return -ENOMEM; - } - - clear_fb_info(fbi); - - fbdev->fbs[i] = fbi; - - ofbi = FB2OFB(fbi); - ofbi->fbdev = fbdev; - ofbi->id = i; - - ofbi->region = &fbdev->regions[i]; - ofbi->region->id = i; - init_rwsem(&ofbi->region->lock); - - /* assign these early, so that fb alloc can use them */ - ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : - OMAP_DSS_ROT_DMA; - ofbi->mirror = def_mirror; - - fbdev->num_fbs++; - } - - DBG("fb_infos allocated\n"); - - /* assign overlays for the fbs */ - for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) { - struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); - - ofbi->overlays[0] = fbdev->overlays[i]; - ofbi->num_overlays = 1; - } - - /* allocate fb memories */ - r = omapfb_allocate_all_fbs(fbdev); - if (r) { - dev_err(fbdev->dev, "failed to allocate fbmem\n"); - return r; - } - - DBG("fbmems allocated\n"); - - /* setup fb_infos */ - for (i = 0; i < fbdev->num_fbs; i++) { - struct fb_info *fbi = fbdev->fbs[i]; - struct omapfb_info *ofbi = FB2OFB(fbi); - - omapfb_get_mem_region(ofbi->region); - r = omapfb_fb_init(fbdev, fbi); - omapfb_put_mem_region(ofbi->region); - - if (r) { - dev_err(fbdev->dev, "failed to setup fb_info\n"); - return r; - } - } - - for (i = 0; i < fbdev->num_fbs; i++) { - struct fb_info *fbi = fbdev->fbs[i]; - struct omapfb_info *ofbi = FB2OFB(fbi); - - if (ofbi->region->size == 0) - continue; - - omapfb_clear_fb(fbi); - } - - DBG("fb_infos initialized\n"); - - for (i = 0; i < fbdev->num_fbs; i++) { - r = register_framebuffer(fbdev->fbs[i]); - if (r != 0) { - dev_err(fbdev->dev, - "registering framebuffer %d failed\n", i); - return r; - } - } - - DBG("framebuffers registered\n"); - - for (i = 0; i < fbdev->num_fbs; i++) { - struct fb_info *fbi = fbdev->fbs[i]; - struct omapfb_info *ofbi = FB2OFB(fbi); - - omapfb_get_mem_region(ofbi->region); - r = omapfb_apply_changes(fbi, 1); - omapfb_put_mem_region(ofbi->region); - - if (r) { - dev_err(fbdev->dev, "failed to change mode\n"); - return r; - } - } - - /* Enable fb0 */ - if (fbdev->num_fbs > 0) { - struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); - - if (ofbi->num_overlays > 0) { - struct omap_overlay *ovl = ofbi->overlays[0]; - - ovl->manager->apply(ovl->manager); - - r = omapfb_overlay_enable(ovl, 1); - - if (r) { - dev_err(fbdev->dev, - "failed to enable overlay\n"); - return r; - } - } - } - - DBG("create_framebuffers done\n"); - - return 0; -} - -static int omapfb_mode_to_timings(const char *mode_str, - struct omap_dss_device *display, - struct omap_video_timings *timings, u8 *bpp) -{ - struct fb_info *fbi; - struct fb_var_screeninfo *var; - struct fb_ops *fbops; - int r; - -#ifdef CONFIG_OMAP2_DSS_VENC - if (strcmp(mode_str, "pal") == 0) { - *timings = omap_dss_pal_timings; - *bpp = 24; - return 0; - } else if (strcmp(mode_str, "ntsc") == 0) { - *timings = omap_dss_ntsc_timings; - *bpp = 24; - return 0; - } -#endif - - /* this is quite a hack, but I wanted to use the modedb and for - * that we need fb_info and var, so we create dummy ones */ - - *bpp = 0; - fbi = NULL; - var = NULL; - fbops = NULL; - - fbi = kzalloc(sizeof(*fbi), GFP_KERNEL); - if (fbi == NULL) { - r = -ENOMEM; - goto err; - } - - var = kzalloc(sizeof(*var), GFP_KERNEL); - if (var == NULL) { - r = -ENOMEM; - goto err; - } - - fbops = kzalloc(sizeof(*fbops), GFP_KERNEL); - if (fbops == NULL) { - r = -ENOMEM; - goto err; - } - - fbi->fbops = fbops; - - r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24); - if (r == 0) { - r = -EINVAL; - goto err; - } - - if (display->driver->get_timings) { - display->driver->get_timings(display, timings); - } else { - timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; - timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; - } - - timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000; - timings->hbp = var->left_margin; - timings->hfp = var->right_margin; - timings->vbp = var->upper_margin; - timings->vfp = var->lower_margin; - timings->hsw = var->hsync_len; - timings->vsw = var->vsync_len; - timings->x_res = var->xres; - timings->y_res = var->yres; - timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ? - OMAPDSS_SIG_ACTIVE_HIGH : - OMAPDSS_SIG_ACTIVE_LOW; - timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ? - OMAPDSS_SIG_ACTIVE_HIGH : - OMAPDSS_SIG_ACTIVE_LOW; - timings->interlace = var->vmode & FB_VMODE_INTERLACED; - - switch (var->bits_per_pixel) { - case 16: - *bpp = 16; - break; - case 24: - case 32: - default: - *bpp = 24; - break; - } - - r = 0; - -err: - kfree(fbi); - kfree(var); - kfree(fbops); - - return r; -} - -static int omapfb_set_def_mode(struct omapfb2_device *fbdev, - struct omap_dss_device *display, char *mode_str) -{ - int r; - u8 bpp; - struct omap_video_timings timings, temp_timings; - struct omapfb_display_data *d; - - r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp); - if (r) - return r; - - d = get_display_data(fbdev, display); - d->bpp_override = bpp; - - if (display->driver->check_timings) { - r = display->driver->check_timings(display, &timings); - if (r) - return r; - } else { - /* If check_timings is not present compare xres and yres */ - if (display->driver->get_timings) { - display->driver->get_timings(display, &temp_timings); - - if (temp_timings.x_res != timings.x_res || - temp_timings.y_res != timings.y_res) - return -EINVAL; - } - } - - if (display->driver->set_timings) - display->driver->set_timings(display, &timings); - - return 0; -} - -static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev, - struct omap_dss_device *dssdev) -{ - struct omapfb_display_data *d; - - BUG_ON(dssdev->driver->get_recommended_bpp == NULL); - - d = get_display_data(fbdev, dssdev); - - if (d->bpp_override != 0) - return d->bpp_override; - - return dssdev->driver->get_recommended_bpp(dssdev); -} - -static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) -{ - char *str, *options, *this_opt; - int r = 0; - - str = kstrdup(def_mode, GFP_KERNEL); - if (!str) - return -ENOMEM; - options = str; - - while (!r && (this_opt = strsep(&options, ",")) != NULL) { - char *p, *display_str, *mode_str; - struct omap_dss_device *display; - int i; - - p = strchr(this_opt, ':'); - if (!p) { - r = -EINVAL; - break; - } - - *p = 0; - display_str = this_opt; - mode_str = p + 1; - - display = NULL; - for (i = 0; i < fbdev->num_displays; ++i) { - if (strcmp(fbdev->displays[i].dssdev->name, - display_str) == 0) { - display = fbdev->displays[i].dssdev; - break; - } - } - - if (!display) { - r = -EINVAL; - break; - } - - r = omapfb_set_def_mode(fbdev, display, mode_str); - if (r) - break; - } - - kfree(str); - - return r; -} - -static void fb_videomode_to_omap_timings(struct fb_videomode *m, - struct omap_dss_device *display, - struct omap_video_timings *t) -{ - if (display->driver->get_timings) { - display->driver->get_timings(display, t); - } else { - t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - t->de_level = OMAPDSS_SIG_ACTIVE_HIGH; - t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; - } - - t->x_res = m->xres; - t->y_res = m->yres; - t->pixelclock = PICOS2KHZ(m->pixclock) * 1000; - t->hsw = m->hsync_len; - t->hfp = m->right_margin; - t->hbp = m->left_margin; - t->vsw = m->vsync_len; - t->vfp = m->lower_margin; - t->vbp = m->upper_margin; - t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ? - OMAPDSS_SIG_ACTIVE_HIGH : - OMAPDSS_SIG_ACTIVE_LOW; - t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ? - OMAPDSS_SIG_ACTIVE_HIGH : - OMAPDSS_SIG_ACTIVE_LOW; - t->interlace = m->vmode & FB_VMODE_INTERLACED; -} - -static int omapfb_find_best_mode(struct omap_dss_device *display, - struct omap_video_timings *timings) -{ - struct fb_monspecs *specs; - u8 *edid; - int r, i, best_idx, len; - - if (!display->driver->read_edid) - return -ENODEV; - - len = 0x80 * 2; - edid = kmalloc(len, GFP_KERNEL); - if (edid == NULL) - return -ENOMEM; - - r = display->driver->read_edid(display, edid, len); - if (r < 0) - goto err1; - - specs = kzalloc(sizeof(*specs), GFP_KERNEL); - if (specs == NULL) { - r = -ENOMEM; - goto err1; - } - - fb_edid_to_monspecs(edid, specs); - - best_idx = -1; - - for (i = 0; i < specs->modedb_len; ++i) { - struct fb_videomode *m; - struct omap_video_timings t; - - m = &specs->modedb[i]; - - if (m->pixclock == 0) - continue; - - /* skip repeated pixel modes */ - if (m->xres == 2880 || m->xres == 1440) - continue; - - if (m->vmode & FB_VMODE_INTERLACED || - m->vmode & FB_VMODE_DOUBLE) - continue; - - fb_videomode_to_omap_timings(m, display, &t); - - r = display->driver->check_timings(display, &t); - if (r == 0) { - best_idx = i; - break; - } - } - - if (best_idx == -1) { - r = -ENOENT; - goto err2; - } - - fb_videomode_to_omap_timings(&specs->modedb[best_idx], display, - timings); - - r = 0; - -err2: - fb_destroy_modedb(specs->modedb); - kfree(specs); -err1: - kfree(edid); - - return r; -} - -static int omapfb_init_display(struct omapfb2_device *fbdev, - struct omap_dss_device *dssdev) -{ - struct omap_dss_driver *dssdrv = dssdev->driver; - struct omapfb_display_data *d; - int r; - - r = dssdrv->enable(dssdev); - if (r) { - dev_warn(fbdev->dev, "Failed to enable display '%s'\n", - dssdev->name); - return r; - } - - d = get_display_data(fbdev, dssdev); - - d->fbdev = fbdev; - - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { - u16 w, h; - - if (auto_update) { - omapfb_start_auto_update(fbdev, dssdev); - d->update_mode = OMAPFB_AUTO_UPDATE; - } else { - d->update_mode = OMAPFB_MANUAL_UPDATE; - } - - if (dssdrv->enable_te) { - r = dssdrv->enable_te(dssdev, 1); - if (r) { - dev_err(fbdev->dev, "Failed to set TE\n"); - return r; - } - } - - dssdrv->get_resolution(dssdev, &w, &h); - r = dssdrv->update(dssdev, 0, 0, w, h); - if (r) { - dev_err(fbdev->dev, - "Failed to update display\n"); - return r; - } - } else { - d->update_mode = OMAPFB_AUTO_UPDATE; - } - - return 0; -} - -static int omapfb_init_connections(struct omapfb2_device *fbdev, - struct omap_dss_device *def_dssdev) -{ - int i, r; - struct omap_overlay_manager *mgr; - - r = def_dssdev->driver->connect(def_dssdev); - if (r) { - dev_err(fbdev->dev, "failed to connect default display\n"); - return r; - } - - for (i = 0; i < fbdev->num_displays; ++i) { - struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; - - if (dssdev == def_dssdev) - continue; - - /* - * We don't care if the connect succeeds or not. We just want to - * connect as many displays as possible. - */ - dssdev->driver->connect(dssdev); - } - - mgr = omapdss_find_mgr_from_display(def_dssdev); - - if (!mgr) { - dev_err(fbdev->dev, "no ovl manager for the default display\n"); - return -EINVAL; - } - - for (i = 0; i < fbdev->num_overlays; i++) { - struct omap_overlay *ovl = fbdev->overlays[i]; - - if (ovl->manager) - ovl->unset_manager(ovl); - - r = ovl->set_manager(ovl, mgr); - if (r) - dev_warn(fbdev->dev, - "failed to connect overlay %s to manager %s\n", - ovl->name, mgr->name); - } - - return 0; -} - -static struct omap_dss_device * -omapfb_find_default_display(struct omapfb2_device *fbdev) -{ - const char *def_name; - int i; - - /* - * Search with the display name from the user or the board file, - * comparing to display names and aliases - */ - - def_name = omapdss_get_default_display_name(); - - if (def_name) { - for (i = 0; i < fbdev->num_displays; ++i) { - struct omap_dss_device *dssdev; - - dssdev = fbdev->displays[i].dssdev; - - if (dssdev->name && strcmp(def_name, dssdev->name) == 0) - return dssdev; - - if (strcmp(def_name, dssdev->alias) == 0) - return dssdev; - } - - /* def_name given but not found */ - return NULL; - } - - /* then look for DT alias display0 */ - for (i = 0; i < fbdev->num_displays; ++i) { - struct omap_dss_device *dssdev; - int id; - - dssdev = fbdev->displays[i].dssdev; - - if (dssdev->dev->of_node == NULL) - continue; - - id = of_alias_get_id(dssdev->dev->of_node, "display"); - if (id == 0) - return dssdev; - } - - /* return the first display we have in the list */ - return fbdev->displays[0].dssdev; -} - -static int omapfb_probe(struct platform_device *pdev) -{ - struct omapfb2_device *fbdev = NULL; - int r = 0; - int i; - struct omap_dss_device *def_display; - struct omap_dss_device *dssdev; - - DBG("omapfb_probe\n"); - - if (omapdss_is_initialized() == false) - return -EPROBE_DEFER; - - if (pdev->num_resources != 0) { - dev_err(&pdev->dev, "probed for an unknown device\n"); - r = -ENODEV; - goto err0; - } - - fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device), - GFP_KERNEL); - if (fbdev == NULL) { - r = -ENOMEM; - goto err0; - } - - if (def_vrfb && !omap_vrfb_supported()) { - def_vrfb = 0; - dev_warn(&pdev->dev, "VRFB is not supported on this hardware, " - "ignoring the module parameter vrfb=y\n"); - } - - r = omapdss_compat_init(); - if (r) - goto err0; - - mutex_init(&fbdev->mtx); - - fbdev->dev = &pdev->dev; - platform_set_drvdata(pdev, fbdev); - - fbdev->num_displays = 0; - dssdev = NULL; - for_each_dss_dev(dssdev) { - struct omapfb_display_data *d; - - omap_dss_get_device(dssdev); - - if (!dssdev->driver) { - dev_warn(&pdev->dev, "no driver for display: %s\n", - dssdev->name); - omap_dss_put_device(dssdev); - continue; - } - - d = &fbdev->displays[fbdev->num_displays++]; - d->dssdev = dssdev; - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) - d->update_mode = OMAPFB_MANUAL_UPDATE; - else - d->update_mode = OMAPFB_AUTO_UPDATE; - } - - if (fbdev->num_displays == 0) { - dev_err(&pdev->dev, "no displays\n"); - r = -EPROBE_DEFER; - goto cleanup; - } - - fbdev->num_overlays = omap_dss_get_num_overlays(); - for (i = 0; i < fbdev->num_overlays; i++) - fbdev->overlays[i] = omap_dss_get_overlay(i); - - fbdev->num_managers = omap_dss_get_num_overlay_managers(); - for (i = 0; i < fbdev->num_managers; i++) - fbdev->managers[i] = omap_dss_get_overlay_manager(i); - - def_display = omapfb_find_default_display(fbdev); - if (def_display == NULL) { - dev_err(fbdev->dev, "failed to find default display\n"); - r = -EPROBE_DEFER; - goto cleanup; - } - - r = omapfb_init_connections(fbdev, def_display); - if (r) { - dev_err(fbdev->dev, "failed to init overlay connections\n"); - goto cleanup; - } - - if (def_mode && strlen(def_mode) > 0) { - if (omapfb_parse_def_modes(fbdev)) - dev_warn(&pdev->dev, "cannot parse default modes\n"); - } else if (def_display && def_display->driver->set_timings && - def_display->driver->check_timings) { - struct omap_video_timings t; - - r = omapfb_find_best_mode(def_display, &t); - - if (r == 0) - def_display->driver->set_timings(def_display, &t); - } - - r = omapfb_create_framebuffers(fbdev); - if (r) - goto cleanup; - - for (i = 0; i < fbdev->num_managers; i++) { - struct omap_overlay_manager *mgr; - mgr = fbdev->managers[i]; - r = mgr->apply(mgr); - if (r) - dev_warn(fbdev->dev, "failed to apply dispc config\n"); - } - - DBG("mgr->apply'ed\n"); - - if (def_display) { - r = omapfb_init_display(fbdev, def_display); - if (r) { - dev_err(fbdev->dev, - "failed to initialize default " - "display\n"); - goto cleanup; - } - } - - DBG("create sysfs for fbs\n"); - r = omapfb_create_sysfs(fbdev); - if (r) { - dev_err(fbdev->dev, "failed to create sysfs entries\n"); - goto cleanup; - } - - if (def_display) { - u16 w, h; - - def_display->driver->get_resolution(def_display, &w, &h); - - dev_info(fbdev->dev, "using display '%s' mode %dx%d\n", - def_display->name, w, h); - } - - return 0; - -cleanup: - omapfb_free_resources(fbdev); - omapdss_compat_uninit(); -err0: - dev_err(&pdev->dev, "failed to setup omapfb\n"); - return r; -} - -static int __exit omapfb_remove(struct platform_device *pdev) -{ - struct omapfb2_device *fbdev = platform_get_drvdata(pdev); - - /* FIXME: wait till completion of pending events */ - - omapfb_remove_sysfs(fbdev); - - omapfb_free_resources(fbdev); - - omapdss_compat_uninit(); - - return 0; -} - -static struct platform_driver omapfb_driver = { - .probe = omapfb_probe, - .remove = __exit_p(omapfb_remove), - .driver = { - .name = "omapfb", - .owner = THIS_MODULE, - }, -}; - -module_param_named(mode, def_mode, charp, 0); -module_param_named(vram, def_vram, charp, 0); -module_param_named(rotate, def_rotate, int, 0); -module_param_named(vrfb, def_vrfb, bool, 0); -module_param_named(mirror, def_mirror, bool, 0); - -module_platform_driver(omapfb_driver); - -MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); -MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c deleted file mode 100644 index 18fa9e1d0033..000000000000 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - * linux/drivers/video/omap2/omapfb-sysfs.c - * - * Copyright (C) 2008 Nokia Corporation - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> - * - * Some code and ideas taken from drivers/video/omap/ driver - * by Imre Deak. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/fb.h> -#include <linux/sysfs.h> -#include <linux/device.h> -#include <linux/uaccess.h> -#include <linux/platform_device.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/omapfb.h> - -#include <video/omapdss.h> -#include <video/omapvrfb.h> - -#include "omapfb.h" - -static ssize_t show_rotate_type(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - - return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type); -} - -static ssize_t store_rotate_type(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_mem_region *rg; - int rot_type; - int r; - - r = kstrtoint(buf, 0, &rot_type); - if (r) - return r; - - if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) - return -EINVAL; - - if (!lock_fb_info(fbi)) - return -ENODEV; - - r = 0; - if (rot_type == ofbi->rotation_type) - goto out; - - rg = omapfb_get_mem_region(ofbi->region); - - if (rg->size) { - r = -EBUSY; - goto put_region; - } - - ofbi->rotation_type = rot_type; - - /* - * Since the VRAM for this FB is not allocated at the moment we don't - * need to do any further parameter checking at this point. - */ -put_region: - omapfb_put_mem_region(rg); -out: - unlock_fb_info(fbi); - - return r ? r : count; -} - - -static ssize_t show_mirror(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - - return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror); -} - -static ssize_t store_mirror(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - bool mirror; - int r; - struct fb_var_screeninfo new_var; - - r = strtobool(buf, &mirror); - if (r) - return r; - - if (!lock_fb_info(fbi)) - return -ENODEV; - - ofbi->mirror = mirror; - - omapfb_get_mem_region(ofbi->region); - - memcpy(&new_var, &fbi->var, sizeof(new_var)); - r = check_fb_var(fbi, &new_var); - if (r) - goto out; - memcpy(&fbi->var, &new_var, sizeof(fbi->var)); - - set_fb_fix(fbi); - - r = omapfb_apply_changes(fbi, 0); - if (r) - goto out; - - r = count; -out: - omapfb_put_mem_region(ofbi->region); - - unlock_fb_info(fbi); - - return r; -} - -static ssize_t show_overlays(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - ssize_t l = 0; - int t; - - if (!lock_fb_info(fbi)) - return -ENODEV; - omapfb_lock(fbdev); - - for (t = 0; t < ofbi->num_overlays; t++) { - struct omap_overlay *ovl = ofbi->overlays[t]; - int ovlnum; - - for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum) - if (ovl == fbdev->overlays[ovlnum]) - break; - - l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", - t == 0 ? "" : ",", ovlnum); - } - - l += snprintf(buf + l, PAGE_SIZE - l, "\n"); - - omapfb_unlock(fbdev); - unlock_fb_info(fbi); - - return l; -} - -static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev, - struct omap_overlay *ovl) -{ - int i, t; - - for (i = 0; i < fbdev->num_fbs; i++) { - struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); - - for (t = 0; t < ofbi->num_overlays; t++) { - if (ofbi->overlays[t] == ovl) - return ofbi; - } - } - - return NULL; -} - -static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB]; - struct omap_overlay *ovl; - int num_ovls, r, i; - int len; - bool added = false; - - num_ovls = 0; - - len = strlen(buf); - if (buf[len - 1] == '\n') - len = len - 1; - - if (!lock_fb_info(fbi)) - return -ENODEV; - omapfb_lock(fbdev); - - if (len > 0) { - char *p = (char *)buf; - int ovlnum; - - while (p < buf + len) { - int found; - if (num_ovls == OMAPFB_MAX_OVL_PER_FB) { - r = -EINVAL; - goto out; - } - - ovlnum = simple_strtoul(p, &p, 0); - if (ovlnum > fbdev->num_overlays) { - r = -EINVAL; - goto out; - } - - found = 0; - for (i = 0; i < num_ovls; ++i) { - if (ovls[i] == fbdev->overlays[ovlnum]) { - found = 1; - break; - } - } - - if (!found) - ovls[num_ovls++] = fbdev->overlays[ovlnum]; - - p++; - } - } - - for (i = 0; i < num_ovls; ++i) { - struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]); - if (ofbi2 && ofbi2 != ofbi) { - dev_err(fbdev->dev, "overlay already in use\n"); - r = -EINVAL; - goto out; - } - } - - /* detach unused overlays */ - for (i = 0; i < ofbi->num_overlays; ++i) { - int t, found; - - ovl = ofbi->overlays[i]; - - found = 0; - - for (t = 0; t < num_ovls; ++t) { - if (ovl == ovls[t]) { - found = 1; - break; - } - } - - if (found) - continue; - - DBG("detaching %d\n", ofbi->overlays[i]->id); - - omapfb_get_mem_region(ofbi->region); - - omapfb_overlay_enable(ovl, 0); - - if (ovl->manager) - ovl->manager->apply(ovl->manager); - - omapfb_put_mem_region(ofbi->region); - - for (t = i + 1; t < ofbi->num_overlays; t++) { - ofbi->rotation[t-1] = ofbi->rotation[t]; - ofbi->overlays[t-1] = ofbi->overlays[t]; - } - - ofbi->num_overlays--; - i--; - } - - for (i = 0; i < num_ovls; ++i) { - int t, found; - - ovl = ovls[i]; - - found = 0; - - for (t = 0; t < ofbi->num_overlays; ++t) { - if (ovl == ofbi->overlays[t]) { - found = 1; - break; - } - } - - if (found) - continue; - ofbi->rotation[ofbi->num_overlays] = 0; - ofbi->overlays[ofbi->num_overlays++] = ovl; - - added = true; - } - - if (added) { - omapfb_get_mem_region(ofbi->region); - - r = omapfb_apply_changes(fbi, 0); - - omapfb_put_mem_region(ofbi->region); - - if (r) - goto out; - } - - r = count; -out: - omapfb_unlock(fbdev); - unlock_fb_info(fbi); - - return r; -} - -static ssize_t show_overlays_rotate(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - ssize_t l = 0; - int t; - - if (!lock_fb_info(fbi)) - return -ENODEV; - - for (t = 0; t < ofbi->num_overlays; t++) { - l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", - t == 0 ? "" : ",", ofbi->rotation[t]); - } - - l += snprintf(buf + l, PAGE_SIZE - l, "\n"); - - unlock_fb_info(fbi); - - return l; -} - -static ssize_t store_overlays_rotate(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - int num_ovls = 0, r, i; - int len; - bool changed = false; - u8 rotation[OMAPFB_MAX_OVL_PER_FB]; - - len = strlen(buf); - if (buf[len - 1] == '\n') - len = len - 1; - - if (!lock_fb_info(fbi)) - return -ENODEV; - - if (len > 0) { - char *p = (char *)buf; - - while (p < buf + len) { - int rot; - - if (num_ovls == ofbi->num_overlays) { - r = -EINVAL; - goto out; - } - - rot = simple_strtoul(p, &p, 0); - if (rot < 0 || rot > 3) { - r = -EINVAL; - goto out; - } - - if (ofbi->rotation[num_ovls] != rot) - changed = true; - - rotation[num_ovls++] = rot; - - p++; - } - } - - if (num_ovls != ofbi->num_overlays) { - r = -EINVAL; - goto out; - } - - if (changed) { - for (i = 0; i < num_ovls; ++i) - ofbi->rotation[i] = rotation[i]; - - omapfb_get_mem_region(ofbi->region); - - r = omapfb_apply_changes(fbi, 0); - - omapfb_put_mem_region(ofbi->region); - - if (r) - goto out; - - /* FIXME error handling? */ - } - - r = count; -out: - unlock_fb_info(fbi); - - return r; -} - -static ssize_t show_size(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - - return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size); -} - -static ssize_t store_size(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omap_dss_device *display = fb2display(fbi); - struct omapfb2_mem_region *rg; - unsigned long size; - int r; - int i; - - r = kstrtoul(buf, 0, &size); - if (r) - return r; - - size = PAGE_ALIGN(size); - - if (!lock_fb_info(fbi)) - return -ENODEV; - - if (display && display->driver->sync) - display->driver->sync(display); - - rg = ofbi->region; - - down_write_nested(&rg->lock, rg->id); - atomic_inc(&rg->lock_count); - - if (atomic_read(&rg->map_count)) { - r = -EBUSY; - goto out; - } - - for (i = 0; i < fbdev->num_fbs; i++) { - struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]); - int j; - - if (ofbi2->region != rg) - continue; - - for (j = 0; j < ofbi2->num_overlays; j++) { - struct omap_overlay *ovl; - ovl = ofbi2->overlays[j]; - if (ovl->is_enabled(ovl)) { - r = -EBUSY; - goto out; - } - } - } - - if (size != ofbi->region->size) { - r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type); - if (r) { - dev_err(dev, "realloc fbmem failed\n"); - goto out; - } - } - - r = count; -out: - atomic_dec(&rg->lock_count); - up_write(&rg->lock); - - unlock_fb_info(fbi); - - return r; -} - -static ssize_t show_phys(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - - return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr); -} - -static ssize_t show_virt(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct omapfb_info *ofbi = FB2OFB(fbi); - - return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr); -} - -static ssize_t show_upd_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - enum omapfb_update_mode mode; - int r; - - r = omapfb_get_update_mode(fbi, &mode); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode); -} - -static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - unsigned mode; - int r; - - r = kstrtouint(buf, 0, &mode); - if (r) - return r; - - r = omapfb_set_update_mode(fbi, mode); - if (r) - return r; - - return count; -} - -static struct device_attribute omapfb_attrs[] = { - __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type, - store_rotate_type), - __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror), - __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size), - __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays), - __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate, - store_overlays_rotate), - __ATTR(phys_addr, S_IRUGO, show_phys, NULL), - __ATTR(virt_addr, S_IRUGO, show_virt, NULL), - __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode), -}; - -int omapfb_create_sysfs(struct omapfb2_device *fbdev) -{ - int i; - int r; - - DBG("create sysfs for fbs\n"); - for (i = 0; i < fbdev->num_fbs; i++) { - int t; - for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) { - r = device_create_file(fbdev->fbs[i]->dev, - &omapfb_attrs[t]); - - if (r) { - dev_err(fbdev->dev, "failed to create sysfs " - "file\n"); - return r; - } - } - } - - return 0; -} - -void omapfb_remove_sysfs(struct omapfb2_device *fbdev) -{ - int i, t; - - DBG("remove sysfs for fbs\n"); - for (i = 0; i < fbdev->num_fbs; i++) { - for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) - device_remove_file(fbdev->fbs[i]->dev, - &omapfb_attrs[t]); - } -} - diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h deleted file mode 100644 index 623cd872a367..000000000000 --- a/drivers/video/omap2/omapfb/omapfb.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * linux/drivers/video/omap2/omapfb.h - * - * Copyright (C) 2008 Nokia Corporation - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> - * - * Some code and ideas taken from drivers/video/omap/ driver - * by Imre Deak. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__ -#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__ - -#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT -#define DEBUG -#endif - -#include <linux/rwsem.h> -#include <linux/dma-attrs.h> -#include <linux/dma-mapping.h> - -#include <video/omapdss.h> - -#ifdef DEBUG -extern bool omapfb_debug; -#define DBG(format, ...) \ - do { \ - if (omapfb_debug) \ - printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__); \ - } while (0) -#else -#define DBG(format, ...) -#endif - -#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par)) - -/* max number of overlays to which a framebuffer data can be direct */ -#define OMAPFB_MAX_OVL_PER_FB 3 - -struct omapfb2_mem_region { - int id; - struct dma_attrs attrs; - void *token; - dma_addr_t dma_handle; - u32 paddr; - void __iomem *vaddr; - struct vrfb vrfb; - unsigned long size; - u8 type; /* OMAPFB_PLANE_MEM_* */ - bool alloc; /* allocated by the driver */ - bool map; /* kernel mapped by the driver */ - atomic_t map_count; - struct rw_semaphore lock; - atomic_t lock_count; -}; - -/* appended to fb_info */ -struct omapfb_info { - int id; - struct omapfb2_mem_region *region; - int num_overlays; - struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; - struct omapfb2_device *fbdev; - enum omap_dss_rotation_type rotation_type; - u8 rotation[OMAPFB_MAX_OVL_PER_FB]; - bool mirror; -}; - -struct omapfb_display_data { - struct omapfb2_device *fbdev; - struct omap_dss_device *dssdev; - u8 bpp_override; - enum omapfb_update_mode update_mode; - bool auto_update_work_enabled; - struct delayed_work auto_update_work; -}; - -struct omapfb2_device { - struct device *dev; - struct mutex mtx; - - u32 pseudo_palette[17]; - - int state; - - unsigned num_fbs; - struct fb_info *fbs[10]; - struct omapfb2_mem_region regions[10]; - - unsigned num_displays; - struct omapfb_display_data displays[10]; - unsigned num_overlays; - struct omap_overlay *overlays[10]; - unsigned num_managers; - struct omap_overlay_manager *managers[10]; - - struct workqueue_struct *auto_update_wq; -}; - -struct omapfb_colormode { - enum omap_color_mode dssmode; - u32 bits_per_pixel; - u32 nonstd; - struct fb_bitfield red; - struct fb_bitfield green; - struct fb_bitfield blue; - struct fb_bitfield transp; -}; - -void set_fb_fix(struct fb_info *fbi); -int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var); -int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type); -int omapfb_apply_changes(struct fb_info *fbi, int init); - -int omapfb_create_sysfs(struct omapfb2_device *fbdev); -void omapfb_remove_sysfs(struct omapfb2_device *fbdev); - -int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); - -int dss_mode_to_fb_mode(enum omap_color_mode dssmode, - struct fb_var_screeninfo *var); - -int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, - u16 posx, u16 posy, u16 outw, u16 outh); - -void omapfb_start_auto_update(struct omapfb2_device *fbdev, - struct omap_dss_device *display); -void omapfb_stop_auto_update(struct omapfb2_device *fbdev, - struct omap_dss_device *display); -int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode); -int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode); - -/* find the display connected to this fb, if any */ -static inline struct omap_dss_device *fb2display(struct fb_info *fbi) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omap_overlay *ovl; - - /* XXX: returns the display connected to first attached overlay */ - - if (ofbi->num_overlays == 0) - return NULL; - - ovl = ofbi->overlays[0]; - - return ovl->get_device(ovl); -} - -static inline struct omapfb_display_data *get_display_data( - struct omapfb2_device *fbdev, struct omap_dss_device *dssdev) -{ - int i; - - for (i = 0; i < fbdev->num_displays; ++i) - if (fbdev->displays[i].dssdev == dssdev) - return &fbdev->displays[i]; - - /* This should never happen */ - BUG(); - return NULL; -} - -static inline void omapfb_lock(struct omapfb2_device *fbdev) -{ - mutex_lock(&fbdev->mtx); -} - -static inline void omapfb_unlock(struct omapfb2_device *fbdev) -{ - mutex_unlock(&fbdev->mtx); -} - -static inline int omapfb_overlay_enable(struct omap_overlay *ovl, - int enable) -{ - if (enable) - return ovl->enable(ovl); - else - return ovl->disable(ovl); -} - -static inline struct omapfb2_mem_region * -omapfb_get_mem_region(struct omapfb2_mem_region *rg) -{ - down_read_nested(&rg->lock, rg->id); - atomic_inc(&rg->lock_count); - return rg; -} - -static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg) -{ - atomic_dec(&rg->lock_count); - up_read(&rg->lock); -} - -#endif |