diff options
Diffstat (limited to 'drivers/video/omap2/omapfb')
-rw-r--r-- | drivers/video/omap2/omapfb/Kconfig | 1 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-ioctl.c | 48 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 212 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-sysfs.c | 6 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb.h | 20 |
5 files changed, 171 insertions, 116 deletions
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig index 4ea17dc3258c..4cb12ce68855 100644 --- a/drivers/video/omap2/omapfb/Kconfig +++ b/drivers/video/omap2/omapfb/Kconfig @@ -2,7 +2,6 @@ menuconfig FB_OMAP2 tristate "OMAP2+ frame buffer support" depends on FB && OMAP2_DSS && !DRM_OMAP - select OMAP2_VRAM select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 select FB_CFB_FILLRECT select FB_CFB_COPYAREA diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index d630b26a005c..d30b45d72649 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -28,10 +28,10 @@ #include <linux/omapfb.h> #include <linux/vmalloc.h> #include <linux/export.h> +#include <linux/sizes.h> #include <video/omapdss.h> -#include <plat/vrfb.h> -#include <plat/vram.h> +#include <video/omapvrfb.h> #include "omapfb.h" @@ -211,6 +211,7 @@ 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; @@ -220,6 +221,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) size = PAGE_ALIGN(mi->size); + if (display && display->driver->sync) + display->driver->sync(display); + rg = ofbi->region; down_write_nested(&rg->lock, rg->id); @@ -279,7 +283,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) return 0; } -static int omapfb_update_window_nolock(struct fb_info *fbi, +static int omapfb_update_window(struct fb_info *fbi, u32 x, u32 y, u32 w, u32 h) { struct omap_dss_device *display = fb2display(fbi); @@ -299,27 +303,6 @@ static int omapfb_update_window_nolock(struct fb_info *fbi, return display->driver->update(display, x, y, w, h); } -/* This function is exported for SGX driver use */ -int omapfb_update_window(struct fb_info *fbi, - u32 x, u32 y, u32 w, u32 h) -{ - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - int r; - - if (!lock_fb_info(fbi)) - return -ENODEV; - omapfb_lock(fbdev); - - r = omapfb_update_window_nolock(fbi, x, y, w, h); - - omapfb_unlock(fbdev); - unlock_fb_info(fbi); - - return r; -} -EXPORT_SYMBOL(omapfb_update_window); - int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode) { @@ -646,7 +629,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) break; } - r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y, + r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y, p.uwnd_o.width, p.uwnd_o.height); break; @@ -663,7 +646,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) break; } - r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y, + r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y, p.uwnd.width, p.uwnd.height); break; @@ -853,14 +836,15 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) break; case OMAPFB_GET_VRAM_INFO: { - unsigned long vram, free, largest; - DBG("ioctl GET_VRAM_INFO\n"); - omap_vram_get_info(&vram, &free, &largest); - p.vram_info.total = vram; - p.vram_info.free = free; - p.vram_info.largest_free_block = largest; + /* + * 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))) diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 16db1589bd91..ca585ef37f25 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -31,9 +31,7 @@ #include <linux/omapfb.h> #include <video/omapdss.h> -#include <plat/cpu.h> -#include <plat/vram.h> -#include <plat/vrfb.h> +#include <video/omapvrfb.h> #include "omapfb.h" @@ -1259,11 +1257,10 @@ static int omapfb_blank(int blank, struct fb_info *fbi) switch (blank) { case FB_BLANK_UNBLANK: - if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) + if (display->state == OMAP_DSS_DISPLAY_ACTIVE) goto exit; - if (display->driver->resume) - r = display->driver->resume(display); + r = display->driver->enable(display); if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) && d->update_mode == OMAPFB_AUTO_UPDATE && @@ -1284,8 +1281,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi) if (d->auto_update_work_enabled) omapfb_stop_auto_update(fbdev, display); - if (display->driver->suspend) - r = display->driver->suspend(display); + display->driver->disable(display); break; @@ -1336,24 +1332,25 @@ static void omapfb_free_fbmem(struct fb_info *fbi) rg = ofbi->region; - WARN_ON(atomic_read(&rg->map_count)); - - if (rg->paddr) - if (omap_vram_free(rg->paddr, rg->size)) - dev_err(fbdev->dev, "VRAM FREE failed\n"); + if (rg->token == NULL) + return; - if (rg->vaddr) - iounmap(rg->vaddr); + 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]); - omap_vrfb_release_ctx(&rg->vrfb); 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; @@ -1388,7 +1385,9 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb2_device *fbdev = ofbi->fbdev; struct omapfb2_mem_region *rg; - void __iomem *vaddr; + void *token; + DEFINE_DMA_ATTRS(attrs); + dma_addr_t dma_handle; int r; rg = ofbi->region; @@ -1403,42 +1402,40 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, size = PAGE_ALIGN(size); - if (!paddr) { - DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); - r = omap_vram_alloc(size, &paddr); - } else { - DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr, - ofbi->id); - r = omap_vram_reserve(paddr, size); - } + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); - if (r) { + 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; } - if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) { - vaddr = ioremap_wc(paddr, size); - - if (!vaddr) { - dev_err(fbdev->dev, "failed to ioremap framebuffer\n"); - omap_vram_free(paddr, size); - return -ENOMEM; - } + DBG("allocated VRAM paddr %lx, vaddr %p\n", + (unsigned long)dma_handle, token); - DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr); - } else { + 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; } - - vaddr = NULL; } - rg->paddr = paddr; - rg->vaddr = vaddr; + 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; @@ -1532,6 +1529,9 @@ static int omapfb_parse_vram_param(const char *param, int max_entries, } + WARN_ONCE(paddr, + "reserving memory at predefined address not supported\n"); + paddrs[fbnum] = paddr; sizes[fbnum] = size; @@ -1611,7 +1611,6 @@ 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 omap_dss_device *display = fb2display(fbi); struct omapfb2_mem_region *rg = ofbi->region; unsigned long old_size = rg->size; unsigned long old_paddr = rg->paddr; @@ -1626,9 +1625,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) if (old_size == size && old_type == type) return 0; - if (display && display->driver->sync) - display->driver->sync(display); - omapfb_free_fbmem(fbi); if (size == 0) { @@ -1883,7 +1879,6 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev) } dev_set_drvdata(fbdev->dev, NULL); - kfree(fbdev); } static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) @@ -2259,26 +2254,28 @@ static int omapfb_find_best_mode(struct omap_dss_device *display, { struct fb_monspecs *specs; u8 *edid; - int r, i, best_xres, best_idx, len; + 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); - if (edid[126] > 0) - fb_edid_add_monspecs(edid + 0x80, specs); - - best_xres = 0; best_idx = -1; for (i = 0; i < specs->modedb_len; ++i) { @@ -2294,16 +2291,20 @@ static int omapfb_find_best_mode(struct omap_dss_device *display, 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_xres < m->xres) { - best_xres = m->xres; + if (r == 0) { best_idx = i; + break; } } - if (best_xres == 0) { + if (best_idx == -1) { r = -ENOENT; goto err2; } @@ -2372,15 +2373,62 @@ static int omapfb_init_display(struct omapfb2_device *fbdev, 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; + + if (!def_dssdev->output) { + dev_err(fbdev->dev, "no output for the default display\n"); + return -EINVAL; + } + + for (i = 0; i < fbdev->num_displays; ++i) { + struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; + struct omap_dss_output *out = dssdev->output; + + mgr = omap_dss_get_overlay_manager(dssdev->channel); + + if (!mgr || !out) + continue; + + if (mgr->output) + mgr->unset_output(mgr); + + mgr->set_output(mgr, out); + } + + mgr = def_dssdev->output->manager; + + 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 int __init omapfb_probe(struct platform_device *pdev) { struct omapfb2_device *fbdev = NULL; int r = 0; int i; - struct omap_overlay *ovl; struct omap_dss_device *def_display; struct omap_dss_device *dssdev; - struct omap_dss_device *ovl_device; DBG("omapfb_probe\n"); @@ -2390,28 +2438,28 @@ static int __init omapfb_probe(struct platform_device *pdev) goto err0; } - fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL); + fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device), + GFP_KERNEL); if (fbdev == NULL) { r = -ENOMEM; goto err0; } - /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE - * available for OMAP2 and OMAP3 - */ - if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) { + 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); - r = 0; fbdev->num_displays = 0; dssdev = NULL; for_each_dss_dev(dssdev) { @@ -2434,9 +2482,6 @@ static int __init omapfb_probe(struct platform_device *pdev) d->update_mode = OMAPFB_AUTO_UPDATE; } - if (r) - goto cleanup; - if (fbdev->num_displays == 0) { dev_err(&pdev->dev, "no displays\n"); r = -EINVAL; @@ -2451,15 +2496,33 @@ static int __init omapfb_probe(struct platform_device *pdev) for (i = 0; i < fbdev->num_managers; i++) fbdev->managers[i] = omap_dss_get_overlay_manager(i); - /* gfx overlay should be the default one. find a display - * connected to that, and use it as default display */ - ovl = omap_dss_get_overlay(0); - ovl_device = ovl->get_device(ovl); - if (ovl_device) { - def_display = ovl_device; - } else { - dev_warn(&pdev->dev, "cannot find default display\n"); - def_display = NULL; + def_display = NULL; + + for (i = 0; i < fbdev->num_displays; ++i) { + struct omap_dss_device *dssdev; + const char *def_name; + + def_name = omapdss_get_default_display_name(); + + dssdev = fbdev->displays[i].dssdev; + + if (def_name == NULL || + (dssdev->name && strcmp(def_name, dssdev->name) == 0)) { + def_display = dssdev; + break; + } + } + + if (def_display == NULL) { + dev_err(fbdev->dev, "failed to find default display\n"); + r = -EINVAL; + 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) { @@ -2510,6 +2573,7 @@ static int __init omapfb_probe(struct platform_device *pdev) cleanup: omapfb_free_resources(fbdev); + omapdss_compat_uninit(); err0: dev_err(&pdev->dev, "failed to setup omapfb\n"); return r; @@ -2525,6 +2589,8 @@ static int __exit omapfb_remove(struct platform_device *pdev) omapfb_free_resources(fbdev); + omapdss_compat_uninit(); + return 0; } diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index e8d8cc76a435..18fa9e1d0033 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c @@ -30,7 +30,7 @@ #include <linux/omapfb.h> #include <video/omapdss.h> -#include <plat/vrfb.h> +#include <video/omapvrfb.h> #include "omapfb.h" @@ -441,6 +441,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, 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; @@ -455,6 +456,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, 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); diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index 5ced9b334d35..623cd872a367 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h @@ -28,6 +28,8 @@ #endif #include <linux/rwsem.h> +#include <linux/dma-attrs.h> +#include <linux/dma-mapping.h> #include <video/omapdss.h> @@ -49,6 +51,9 @@ extern bool omapfb_debug; 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; @@ -124,9 +129,6 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev); int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); -int omapfb_update_window(struct fb_info *fbi, - u32 x, u32 y, u32 w, u32 h); - int dss_mode_to_fb_mode(enum omap_color_mode dssmode, struct fb_var_screeninfo *var); @@ -144,16 +146,16 @@ int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode); static inline struct omap_dss_device *fb2display(struct fb_info *fbi) { struct omapfb_info *ofbi = FB2OFB(fbi); - int i; + struct omap_overlay *ovl; /* XXX: returns the display connected to first attached overlay */ - for (i = 0; i < ofbi->num_overlays; i++) { - struct omap_overlay *ovl = ofbi->overlays[i]; - return ovl->get_device(ovl); - } + if (ofbi->num_overlays == 0) + return NULL; - return NULL; + ovl = ofbi->overlays[0]; + + return ovl->get_device(ovl); } static inline struct omapfb_display_data *get_display_data( |