Ejemplo n.º 1
0
/*
 * Present frame and synchronize with the display to prevent tearing
 * On DSI panels the sync function is used to handle FRAMEDONE IRQ
 * On DPI panels the wait_for_vsync is used to handle VSYNC IRQ
 * in: psDevInfo
 */
void OMAPLFBPresentSync(OMAPLFB_DEVINFO *psDevInfo,
	OMAPLFB_FLIP_ITEM *psFlipItem)
{
	struct fb_info *framebuffer = psDevInfo->psLINFBInfo;
	struct omapfb_info *ofbi = FB2OFB(framebuffer);
	struct omap_dss_device *display;
	struct omapfb2_device *fbdev = ofbi->fbdev;
	struct omap_dss_driver *driver;
	struct omap_overlay_manager *manager;
	int err = 1;

	omapfb_lock(fbdev);

// [email protected] Backup the Display device for using later [START]
#if defined(CONFIG_MACH_LGE_OMAP3)
	Prev_disp = display = fb2display(framebuffer);
#else
	display = fb2display(framebuffer);
#endif	
// [email protected] Backup the Display device for using later [END]
	/* The framebuffer doesn't have a display attached, just bail out */
	if (!display) {
		omapfb_unlock(fbdev);
		return;
	}

	driver = display->driver;
	manager = display->manager;

	if (driver && driver->sync &&
		driver->get_update_mode(display) == OMAP_DSS_UPDATE_MANUAL) {
		/* Wait first for the DSI bus to be released then update */
		err = driver->sync(display);
		OMAPLFBFlipNoLock(psDevInfo->psSwapChain,
			(unsigned long)psFlipItem->sSysAddr->uiAddr);
	} else if (manager && manager->wait_for_vsync) {
		/*
		 * Update the video pipelines registers then wait until the
		 * frame is shown with a VSYNC
		 */
		OMAPLFBFlipNoLock(psDevInfo->psSwapChain,
			(unsigned long)psFlipItem->sSysAddr->uiAddr);
		err = manager->wait_for_vsync(manager);
	}

	if (err)
		WARNING_PRINTK("Unable to sync with display %u!",
			psDevInfo->uDeviceID);

	omapfb_unlock(fbdev);
}
Ejemplo n.º 2
0
static int omapfb_get_update_mode(struct fb_info *fbi,
		enum omapfb_update_mode *mode)
{
	struct omapfb_info *ofbi = FB2OFB(fbi);
	struct omapfb2_device *fbdev = ofbi->fbdev;
	struct omap_display *display = fb2display(fbi);
	enum omap_dss_update_mode m;

	if (!display || !display->get_update_mode)
		return -EINVAL;

	omapfb_lock(fbdev);
	m = display->get_update_mode(display);
	omapfb_unlock(fbdev);

	switch (m) {
	case OMAP_DSS_UPDATE_DISABLED:
		*mode = OMAPFB_UPDATE_DISABLED;
		break;
	case OMAP_DSS_UPDATE_AUTO:
		*mode = OMAPFB_AUTO_UPDATE;
		break;
	case OMAP_DSS_UPDATE_MANUAL:
		*mode = OMAPFB_MANUAL_UPDATE;
		break;
	default:
		BUG();
	}

	return 0;
}
Ejemplo n.º 3
0
static ssize_t show_managers(struct device *dev, struct device_attribute *attr,
		char *buf)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	ssize_t l = 0, size = PAGE_SIZE;
	int i;

	omapfb_lock(fbdev);

	for (i = 0; i < fbdev->num_managers; i++) {
		struct omap_display *display;
		struct omap_overlay_manager *mgr;

		mgr = fbdev->managers[i];
		display = mgr->display;

		l += snprintf(buf + l, size - l, "%s t:%s trans:%d type:%d key:%08x alpha:%d\n",
				mgr->name, display ? display->name : "none", 
				mgr->info.trans_enabled, 
				mgr->info.trans_key_type,
				mgr->info.trans_key,
				mgr->info.alpha_enabled);
	}

	omapfb_unlock(fbdev);

	return l;
}
Ejemplo n.º 4
0
static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
{
	struct omapfb_info *ofbi = FB2OFB(fbi);
	struct omapfb2_device *fbdev = ofbi->fbdev;

	omapfb_lock(fbdev);

	if (ofbi->num_overlays != 1) {
		memset(pi, 0, sizeof(*pi));
	} else {
		struct omap_overlay_info *ovli;
		struct omap_overlay *ovl;

		ovl = ofbi->overlays[0];
		ovli = &ovl->info;

		pi->pos_x = ovli->pos_x;
		pi->pos_y = ovli->pos_y;
		pi->enabled = ovli->enabled;
		pi->channel_out = 0; /* xxx */
		pi->mirror = 0;
		pi->out_width = ovli->out_width;
		pi->out_height = ovli->out_height;
	}

	omapfb_unlock(fbdev);

	return 0;
}
Ejemplo n.º 5
0
static 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;
	struct omap_display *display = fb2display(fbi);
	int dw, dh;

	if (!display)
		return 0;

	if (w == 0 || h == 0)
		return 0;

	display->get_resolution(display, &dw, &dh);

	if (x + w > dw || y + h > dh)
		return -EINVAL;

	omapfb_lock(fbdev);
	display->update(display, x, y, w, h);
	omapfb_unlock(fbdev);

	return 0;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
static int omapfb_set_update_mode(struct fb_info *fbi,
				   enum omapfb_update_mode mode)
{
	struct omapfb_info *ofbi = FB2OFB(fbi);
	struct omapfb2_device *fbdev = ofbi->fbdev;
	struct omap_display *display = fb2display(fbi);
	enum omap_dss_update_mode um;
	int r;

	if (!display || !display->set_update_mode)
		return -EINVAL;

	switch (mode) {
	case OMAPFB_UPDATE_DISABLED:
		um = OMAP_DSS_UPDATE_DISABLED;
		break;

	case OMAPFB_AUTO_UPDATE:
		um = OMAP_DSS_UPDATE_AUTO;
		break;

	case OMAPFB_MANUAL_UPDATE:
		um = OMAP_DSS_UPDATE_MANUAL;
		break;

	default:
		return -EINVAL;
	}

	omapfb_lock(fbdev);
	r = display->set_update_mode(display, um);
	omapfb_unlock(fbdev);

	return r;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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_display *display = fb2display(fbi);
	struct omap_overlay *ovl;
	int r = 0;

	DBG("omapfb_setup_plane\n");

	omapfb_lock(fbdev);

	if (ofbi->num_overlays != 1) {
		r = -EINVAL;
		goto out;
	}

	/* XXX uses only the first overlay */
	ovl = ofbi->overlays[0];

	if (pi->enabled && !ofbi->region.size) {
		/*
		 * This plane's memory was freed, can't enable it
		 * until it's reallocated.
		 */
		r = -EINVAL;
		goto out;
	}

	if (pi->enabled) {
		r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
				pi->out_width, pi->out_height);
		if (r)
			goto out;
	}

	ovl->enable(ovl, pi->enabled);

	if (ovl->manager)
		ovl->manager->apply(ovl->manager);

	if (display) {
		int w, h;

		if (display->sync)
			display->sync(display);

		display->get_resolution(display, &w, &h);

		if (display->update)
			display->update(display, 0, 0, w, h);
	}

out:
	omapfb_unlock(fbdev);
	if (r)
		dev_err(fbdev->dev, "setup_plane failed\n");
	return r;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
static ssize_t show_displays(struct device *dev, struct device_attribute *attr,
		char *buf)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	ssize_t l = 0, size = PAGE_SIZE;
	int i;
	struct omap_video_timings timings;

	omapfb_lock(fbdev);

	for (i = 0; i < fbdev->num_displays; i++) {
		struct omap_display *display;
		enum omap_dss_update_mode mode = -1;
		int te = 0;
		int rot = 0, mir = 0;

		display = fbdev->displays[i];

		if (display->get_update_mode)
			mode = display->get_update_mode(display);

		if (display->get_te)
			te = display->get_te(display);

		if (display->get_timings)
			display->get_timings(display, &timings);
		else
			memset(&timings, 0, sizeof(timings));

		if (display->get_rotate)
			rot = display->get_rotate(display);

		if (display->get_mirror)
			mir = display->get_mirror(display);

		l += snprintf(buf + l, size - l,
				"%s e:%d u:%d t:%d h:%u/%u/%u/%u "
				"v:%u/%u/%u/%u p:%u r:%d i:%d\n",
				display->name,
				display->state != OMAP_DSS_DISPLAY_DISABLED,
				mode, te,
				timings.x_res,
				timings.hfp, timings.hbp, timings.hsw,
				timings.y_res,
				timings.vfp, timings.vbp, timings.vsw,
				timings.pixel_clock,
				rot, mir);
	}

	omapfb_unlock(fbdev);

	return l;
}
Ejemplo n.º 12
0
void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr)
{
	OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)psSwapChain->pvDevInfo;
	struct fb_info *framebuffer = psDevInfo->psLINFBInfo;
	struct omapfb_info *ofbi = FB2OFB(framebuffer);
	struct omapfb2_device *fbdev = ofbi->fbdev;

	omapfb_lock(fbdev);
	OMAPLFBFlipNoLock(psSwapChain, aPhyAddr);
	omapfb_unlock(fbdev);
}
Ejemplo n.º 13
0
/*
 * Synchronize with the display to prevent tearing
 * On DSI panels the display->sync function is used to handle FRAMEDONE IRQ
 * On DPI panels the display->wait_vsync is used to handle VSYNC IRQ
 * in: psDevInfo
 */
void OMAPLFBPresentSync(OMAPLFB_DEVINFO *psDevInfo,
	OMAPLFB_FLIP_ITEM *psFlipItem)
{
	struct fb_info * framebuffer = psDevInfo->psLINFBInfo;
	struct omapfb_info *ofbi = FB2OFB(framebuffer);
	struct omapfb2_device *fbdev = ofbi->fbdev;
	struct omap_dss_device *display;
	int err = 1;

	omapfb_lock(fbdev);

	display = fb2display(framebuffer);

	/* The framebuffer doesn't have a display attached, just bail out */
	if (!display) {
		omapfb_unlock(fbdev);
		return;
	}

	if (display->sync &&
		display->get_update_mode(display) == OMAP_DSS_UPDATE_MANUAL) {
		/* Wait first for the DSI bus to be released then update */
		err = display->sync(display);
		OMAPLFBFlipNoLock(psDevInfo->psSwapChain,
			(unsigned long)psFlipItem->sSysAddr->uiAddr);
	} else if (display->wait_vsync) {
		/*
		 * Update the video pipelines registers then wait until the
		 * frame is shown with a VSYNC
		 */
		OMAPLFBFlipNoLock(psDevInfo->psSwapChain,
			(unsigned long)psFlipItem->sSysAddr->uiAddr);
		err = display->wait_vsync(display);
	}

	if (err)
		WARNING_PRINTK("Unable to sync with display %u!",
			psDevInfo->uDeviceID);

	omapfb_unlock(fbdev);
}
Ejemplo n.º 14
0
static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
{
	struct omapfb_info *ofbi = FB2OFB(fbi);
	struct omapfb2_device *fbdev = ofbi->fbdev;
	struct omapfb2_mem_region *rg;

	rg = &ofbi->region;
	memset(mi, 0, sizeof(*mi));

	omapfb_lock(fbdev);
	mi->size = rg->size;
	mi->type = rg->type;
	omapfb_unlock(fbdev);

	return 0;
}
Ejemplo n.º 15
0
/* 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;
}
Ejemplo n.º 16
0
static ssize_t show_overlays(struct device *dev, struct device_attribute *attr,
		char *buf)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	ssize_t l = 0, size = PAGE_SIZE;
	int i, mgr_num, alpha;

	omapfb_lock(fbdev);

	for (i = 0; i < fbdev->num_overlays; i++) {
		struct omap_overlay *ovl;
		struct omap_overlay_manager *mgr;

		ovl = fbdev->overlays[i];
		mgr = ovl->manager;

		if (strcmp(ovl->name, "vid1") != 0)
			alpha = ovl->info.global_alpha;
		else
			alpha = -1;
			
		for (mgr_num = 0; mgr_num < fbdev->num_managers; mgr_num++)
			if (fbdev->managers[mgr_num] == mgr)
				break;

		l += snprintf(buf + l, size - l,
			"%s t:%s x:%d y:%d iw:%d ih:%d w:%d h:%d a:%d e:%d\n",
			ovl->name,
			mgr ? mgr->name : "none",
			ovl->info.pos_x,
			ovl->info.pos_y,
			ovl->info.width,
			ovl->info.height,
			ovl->info.out_width,
			ovl->info.out_height,
			alpha,
			ovl->info.enabled);
	}

	omapfb_unlock(fbdev);

	return l;
}
Ejemplo n.º 17
0
void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr)
{
struct omap_overlay* overlay;
	struct omap_overlay_info overlay_info;
	struct fb_info * framebuffer;
	OMAPLFB_DEVINFO	*psDevInfo;
	struct omapfb_info *ofbi;
	struct omapfb2_device *fbdev;
	int i;
	unsigned long fb_offset;

	psDevInfo = (OMAPLFB_DEVINFO *) psSwapChain->pvDevInfo;
	framebuffer = psDevInfo->psLINFBInfo;
	ofbi = FB2OFB(framebuffer);
	fb_offset = aPhyAddr - psDevInfo->sSystemBuffer.sSysAddr.uiAddr;
	fbdev = ofbi->fbdev;

	omapfb_lock(fbdev);

	for(i = 0; i < ofbi->num_overlays ; i++)
	{
		overlay = ofbi->overlays[i];
		overlay->get_overlay_info( overlay, &overlay_info );
		/* If the overlay is not enabled don't update it */
		if(!overlay_info.enabled)
			continue;

		overlay_info.paddr = framebuffer->fix.smem_start + fb_offset;
		overlay_info.vaddr = framebuffer->screen_base + fb_offset;
		overlay->set_overlay_info(overlay, &overlay_info);
		overlay->manager->apply(overlay->manager);

		if(overlay->manager->device->update)
		{
			overlay->manager->device->update(
				overlay->manager->device, 0, 0,
				overlay_info.width,
				overlay_info.height);
		}
	}

	omapfb_unlock(fbdev);

}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
0
static ssize_t show_framebuffers(struct device *dev,
		struct device_attribute *attr,
		char *buf)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	ssize_t l = 0, size = PAGE_SIZE;
	int i, t;

	omapfb_lock(fbdev);

	for (i = 0; i < fbdev->num_fbs; i++) {
		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
		struct omapfb2_mem_region *rg;

		rg = &ofbi->region;

		l += snprintf(buf + l, size - l, "%d p:%08x v:%p size:%lu t:",
				ofbi->id,
				rg->_paddr, rg->_vaddr, rg->size);

		if (ofbi->num_overlays == 0)
			l += snprintf(buf + l, size - l, "none");

		for (t = 0; t < ofbi->num_overlays; t++) {
			struct omap_overlay *ovl;
			ovl = ofbi->overlays[t];

			l += snprintf(buf + l, size - l, "%s%s",
					t == 0 ? "" : ",",
					ovl->name);
		}

		l += snprintf(buf + l, size - l, "\n");
	}

	omapfb_unlock(fbdev);

	return l;
}
Ejemplo n.º 20
0
static ssize_t store_managers(struct device *dev,
		struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	int idx;
	struct omap_overlay_manager *mgr;
	struct omap_display *display;
	char mgrname[10];
	char displayname[10];
	int r;

	idx = 0;
	while (idx < count && buf[idx] != ' ')
		++idx;

	if (idx == count)
		return -EINVAL;

	if (idx >= sizeof(mgrname))
		return -EINVAL;

	strncpy(mgrname, buf, idx);
	mgrname[idx] = 0;
	idx++;

	omapfb_lock(fbdev);

	mgr = find_manager_by_name(fbdev, mgrname);

	if (!mgr) {
		dev_err(dev, "manager not found\n");
		r = -EINVAL;
		goto err;
	}

	r = sscanf(buf + idx, "t:%9s", displayname);

	if (r != 1) {
		r = -EINVAL;
		goto err;
	}

	if (strcmp(displayname, "none") == 0) {
		display = NULL;
	} else {
		display = find_display_by_name(fbdev, displayname);

		if (!display) {
			dev_err(dev, "display not found\n");
			r = -EINVAL;
			goto err;
		}
	}

	if (mgr->display) {
		r = mgr->unset_display(mgr);
		if (r) {
			dev_err(dev, "failed to unset display\n");
			goto err;
		}
	}

	if (display) {
		r = mgr->set_display(mgr, display);
		if (r) {
			dev_err(dev, "failed to set manager\n");
			goto err;
		}

		r = mgr->apply(mgr);
		if (r) {
			dev_err(dev, "failed to apply dispc config\n");
			goto err;
		}
	}

	omapfb_unlock(fbdev);
	return count;

err:
	omapfb_unlock(fbdev);
	return r;
}
Ejemplo n.º 21
0
static ssize_t store_overlays(struct device *dev,
		struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	int idx;
	struct omap_overlay *ovl = NULL;
	struct omap_overlay_manager *mgr;
	int r;
	char ovlname[10];
	int posx, posy, outw, outh;
	int enabled;
	int alpha;
	
	idx = 0;
	while (idx < count && buf[idx] != ' ')
		++idx;

	if (idx == count)
		return -EINVAL;

	if (idx >= sizeof(ovlname))
		return -EINVAL;

	strncpy(ovlname, buf, idx);
	ovlname[idx] = 0;
	idx++;

	omapfb_lock(fbdev);

	ovl = find_overlay_by_name(fbdev, ovlname);

	if (!ovl) {
		dev_err(dev, "ovl not found\n");
		r = -EINVAL;
		goto err;
	}

	DBG("ovl %s found\n", ovl->name);

	mgr = ovl->manager;

	posx = ovl->info.pos_x;
	posy = ovl->info.pos_y;
	outw = ovl->info.out_width;
	outh = ovl->info.out_height;
	if (strcmp(ovl->name, "vid1") != 0)
		alpha = ovl->info.global_alpha;
	else
		alpha = -1;
		
	enabled = ovl->info.enabled;

	while (idx < count) {
		char c;
		int val;
		int len;
		char sval[10];

		r = sscanf(buf + idx, "%c:%d%n", &c, &val, &len);

		if (r != 2) {
			val = 0;

			r = sscanf(buf + idx, "%c:%9s%n", &c, sval, &len);

			if (r != 2) {
				dev_err(dev, "sscanf failed, aborting\n");
				r = -EINVAL;
				goto err;
			}
		} else {
			sval[0] = 0;
		}

		switch (c) {
		case 't':
			if (strcmp(sval, "none") == 0) {
				mgr = NULL;
			} else {
				mgr = find_manager_by_name(fbdev, sval);

				if (mgr == NULL) {
					dev_err(dev, "no such manager\n");
					r = -EINVAL;
					goto err;
				}

				DBG("manager %s found\n", mgr->name);
			}

			break;

		case 'x':
			posx = val;
			break;

		case 'y':
			posy = val;
			break;

		case 'w':
			if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE)
				outw = val;
			break;

		case 'h':
			if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE)
				outh = val;
			break;

		case 'a':
			alpha = val & 0xff;
			break;

		case 'e':
			enabled = val;
			break;

		default:
			dev_err(dev, "unknown option %c\n", c);
			r = -EINVAL;
			goto err;
		}

		idx += len + 1;
	}

	if (strcmp(ovl->name, "vid1") != 0)
		ovl->info.global_alpha = alpha;
	
	r = ovl->setup_output(ovl, posx, posy, outw, outh);
	
	if (r) {
		dev_err(dev, "setup overlay failed\n");
		goto err;
	}

	if (mgr != ovl->manager) {
		/* detach old manager */
		if (ovl->manager) {
			r = ovl->unset_manager(ovl);
			if (r) {
				dev_err(dev, "detach failed\n");
				goto err;
			}
		}

		if (mgr) {
			r = ovl->set_manager(ovl, mgr);
			if (r) {
				dev_err(dev, "Failed to attach overlay\n");
				goto err;
			}
		}
	}

	r = ovl->enable(ovl, enabled);

	if (r) {
		dev_err(dev, "enable overlay failed\n");
		goto err;
	}

	if (mgr) {
		r = mgr->apply(mgr);
		if (r) {
			dev_err(dev, "failed to apply dispc config\n");
			goto err;
		}
	} else {
		ovl->enable(ovl, 0);
	}

	if (mgr && mgr->display && mgr->display->update) {
		int w, h;
		mgr->display->get_resolution(mgr->display, &w, &h);
		mgr->display->update(mgr->display, 0, 0, w, h);
	}

	omapfb_unlock(fbdev);
	return count;

err:
	omapfb_unlock(fbdev);
	return r;
}
Ejemplo n.º 22
0
static ssize_t store_framebuffers(struct device *dev,
		struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	int idx;
	char fbname[3];
	unsigned long fbnum;
	char ovlnames[40];
	int num_ovls = 0;
	struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
	struct fb_info *fbi;
	struct omapfb_info *ofbi;
	int r, i;

	idx = 0;
	while (idx < count && buf[idx] != ' ')
		++idx;

	if (idx == count)
		return -EINVAL;

	if (idx >= sizeof(fbname))
		return -EINVAL;

	strncpy(fbname, buf, idx);
	fbname[idx] = 0;
	idx++;

	if (strict_strtoul(fbname, 10, &fbnum))
		return -EINVAL;

	r = sscanf(buf + idx, "t:%39s", ovlnames);

	if (r != 1) {
		r = -EINVAL;
		goto err;
	}

	omapfb_lock(fbdev);

	if (fbnum >= fbdev->num_fbs) {
		dev_err(dev, "fb not found\n");
		r = -EINVAL;
		goto err;
	}

	fbi = fbdev->fbs[fbnum];
	ofbi = FB2OFB(fbi);

	if (strcmp(ovlnames, "none") == 0) {
		num_ovls = 0;
	} else {
		num_ovls = parse_overlays(fbdev, ovlnames, ovls);

		if (num_ovls == 0) {
			dev_err(dev, "overlays not found\n");
			r = -EINVAL;
			goto err;
		}
	}

	for (i = 0; i < ofbi->num_overlays; i++) {
		r = omapfb_detach_framebuffer(fbi, ofbi->overlays[i]);
		if (r) {
			dev_err(dev, "detach failed\n");
			goto err;
		}
	}

	if (num_ovls > 0) {
		for (i = 0; i < num_ovls; i++) {
			r = omapfb_attach_framebuffer(fbi, ovls[i]);
			if (r) {
				dev_err(dev, "attach failed\n");
				goto err;
			}
		}
	}

	omapfb_unlock(fbdev);
	return count;

err:
	omapfb_unlock(fbdev);
	return r;
}
Ejemplo n.º 23
0
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;
}
Ejemplo n.º 24
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 omapfb2_mem_region *rg;
	struct omap_display *display = fb2display(fbi);
	int r, i;
	size_t size;

	if (mi->type > OMAPFB_MEMTYPE_MAX)
		return -EINVAL;

	size = PAGE_ALIGN(mi->size);

	rg = &ofbi->region;

	omapfb_lock(fbdev);

	for (i = 0; i < ofbi->num_overlays; i++) {
		if (ofbi->overlays[i]->info.enabled) {
			r = -EBUSY;
			goto out;
		}
	}

	if (rg->size != size || rg->type != mi->type) {
		struct fb_var_screeninfo new_var;
		unsigned long old_size = rg->size;

		if (display->sync)
			display->sync(display);

		r = omapfb_realloc_fbmem(fbdev, ofbi->id, size);
		if (r)
			goto out;

		if (old_size != size) {
			if (size) {
				memcpy(&new_var, &fbi->var, sizeof(new_var));
				r = check_fb_var(fbi, &new_var);
				if (r < 0)
					goto out;
				memcpy(&fbi->var, &new_var, sizeof(fbi->var));
				set_fb_fix(fbi);
			} else {
				/*
				 * Set these explicitly to indicate that the
				 * plane memory is dealloce'd, the other
				 * screen parameters in var / fix are invalid.
				 */
				fbi->fix.smem_start = 0;
				fbi->fix.smem_len = 0;
			}
		}
	}

	r = 0;
out:
	omapfb_unlock(fbdev);

	return r;
}
Ejemplo n.º 25
0
static ssize_t store_managers(struct device *dev,
		struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	struct omap_overlay_manager *mgr;
	struct omap_display *display = NULL;
	char displayname[10];
	int r;
	char *s, *tok;
	char str[128];
	struct omap_overlay_manager_info newinfo;
	int apply = 0;
	
	displayname[0] = '\0';
	
	if (strlen(buf) > sizeof(str) - 1)
		return -EINVAL;

	strcpy(str, buf);

	/* remove trailing linefeeds */
	s = str + strlen(str) - 1;
	while (s >= str	&& *s == '\n') {
		*s = 0;
		s--;
	}

	s = str;

	if ((tok = strsep(&s, " ")) == 0)
		return -EINVAL;

	omapfb_lock(fbdev);

	mgr = find_manager_by_name(fbdev, tok);
	if (!mgr) {
		dev_err(dev, "manager not found\n");
		r = -EINVAL;
		goto err;
	}

	newinfo = mgr->info;
	
	while ((tok = strsep(&s, " "))) {
		if (strncmp(tok, "t:", 2) == 0) {
			r = sscanf(tok, "t:%9s", displayname);
			if (r != 1) {
				r = -EINVAL;
				goto err;
			}
		} else if(strncmp(tok, "trans:", 6) == 0) {
			newinfo.trans_enabled = simple_strtoul(tok+6, NULL, 0);
		} else if(strncmp(tok, "type:", 5) == 0) {
			newinfo.trans_key_type = simple_strtoul(tok+5, NULL, 0);
		} else if(strncmp(tok, "key:", 4) == 0) {
			newinfo.trans_key = simple_strtoul(tok+4, NULL, 0);
		} else if(strncmp(tok, "alpha:", 6) == 0) {
			newinfo.alpha_enabled = simple_strtoul(tok+6, NULL, 0);
		} else {
			dev_err(dev, "unknown option\n");
			r = -EINVAL;
			goto err;
		}
	}

	if (memcmp(&newinfo, &mgr->info, sizeof(struct omap_overlay_manager_info)) != 0) {
		mgr->info = newinfo;
		mgr->info_dirty = 1;
		apply = 1;
	}
	
	if (displayname[0] != '\0') {
		if (strcmp(displayname, "none") == 0) {
			display = NULL;
		} else {
			display = find_display_by_name(fbdev, displayname);

			if (!display) {
				dev_err(dev, "display not found: [%s]\n", displayname);
				r = -EINVAL;
				goto err;
			}
		}

		if (mgr->display) {
			r = mgr->unset_display(mgr);
			if (r) {
				dev_err(dev, "failed to unset display\n");
				goto err;
			}
		}

		if (display) {
			r = mgr->set_display(mgr, display);
			if (r) {
				dev_err(dev, "failed to set manager\n");
				goto err;
			}

		}
		
		apply  = 1;
	}
		
	if (apply)  {
		r = mgr->apply(mgr);
		if (r) {
			dev_err(dev, "failed to apply dispc config\n");
			goto err;
		}
	}
	
	omapfb_unlock(fbdev);	
	return count;

err:
	omapfb_unlock(fbdev);
	return r;
}
Ejemplo n.º 26
0
static ssize_t store_displays(struct device *dev,
		struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
	int enable;
	struct omap_video_timings old_timings;
	struct omap_video_timings new_timings;
	enum omap_dss_update_mode mode;
	enum omap_dss_venc_norm new_norm;
	enum omap_dss_venc_type new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
	struct omap_display *display = NULL;
	int r;
	int te, rot, mir;
	char str[128];
	char *s, *tok;

	if (strlen(buf) > sizeof(str) - 1)
		return -EINVAL;

	strcpy(str, buf);

	/* remove trailing linefeeds */
	s = str + strlen(str) - 1;
	while (s >= str	&& *s == '\n') {
		*s = 0;
		s--;
	}

	s = str;

	if ((tok = strsep(&s, " ")) == 0)
		return -EINVAL;

	omapfb_lock(fbdev);

	display = find_display_by_name(fbdev, tok);

	if (!display) {
		dev_err(dev, "display not found: [%s]\n", tok);
		r = -EINVAL;
		goto err;
	}

	enable = display->state != OMAP_DSS_DISPLAY_DISABLED;
	if (display->get_update_mode)
		mode = display->get_update_mode(display);
	else
		mode = 0;

	if (display->get_te)
		te = display->get_te(display);
	else
		te = 0;

	if (display->get_rotate)
		rot = display->get_rotate(display);
	else
		rot = 0;

	if (display->get_mirror)
		mir = display->get_mirror(display);
	else
		mir = 0;

	if (display->get_timings)
		display->get_timings(display, &old_timings);
	else
		memset(&old_timings, 0, sizeof(old_timings));

	memcpy(&new_timings, &old_timings, sizeof(new_timings));

	/* TV norm switching */
	if (display->get_tv_norm)
		new_norm = display->get_tv_norm(display);
	else
		new_norm = -1;
		
	/* TV type switching */
	if (display->get_tv_type)
		new_type = display->get_tv_type(display);
	
	while ((tok = strsep(&s, " "))) {
		char c, *o;

		if (strlen(tok) < 3 || tok[1] != ':') {
			dev_err(dev, "illegal option\n");
			r = -EINVAL;
			goto err;
		}

		c = tok[0];
		o = tok + 2;

		switch (c) {
		case 'e':
			enable = simple_strtoul(o, NULL, 0);
			break;

		case 'u':
			mode = simple_strtoul(o, NULL, 0);
			break;

		case 't':
			te = simple_strtoul(o, NULL, 0);
			break;

		case 'r':
			rot = simple_strtoul(o, NULL, 0);
			break;

		case 'i':
			mir = simple_strtoul(o, NULL, 0);
			break;

		case 'm': {
			unsigned bpp;
			if (omapfb_mode_to_timings(o, &new_timings, &bpp) != 0)
				memset(&new_timings, 0, sizeof(new_timings));

			break;
		}

		case 'h': {
			unsigned xres, hfp, hbp, hsw;

			if (sscanf(o, "%u/%u/%u/%u",
						&xres, &hfp, &hbp, &hsw) != 4) {
				dev_err(dev, "illegal horizontal timings\n");
				r = -EINVAL;
				goto err;
			}

			new_timings.x_res = xres;
			new_timings.hfp = hfp;
			new_timings.hbp = hbp;
			new_timings.hsw = hsw;
			break;
		}

		case 'v': {
			unsigned yres, vfp, vbp, vsw;

			if (sscanf(o, "%u/%u/%u/%u",
						&yres, &vfp, &vbp, &vsw) != 4) {
				dev_err(dev, "illegal vertical timings\n");
				r = -EINVAL;
				goto err;
			}

			new_timings.y_res = yres;
			new_timings.vfp = vfp;
			new_timings.vbp = vbp;
			new_timings.vsw = vsw;
			break;
		}

		case 'p':
			new_timings.pixel_clock = simple_strtoul(o, NULL, 0);
			break;
			
		case 'l':
			new_timings.interlaced = simple_strtoul(o, NULL, 0);
			break;

		case 'n':
			new_norm = simple_strtoul(o, NULL, 0);
			break;

		case 's':
			new_type = simple_strtoul(o, NULL, 0);
			break;
			
		default:
			dev_err(dev, "unknown option %c\n", c);
			r = -EINVAL;
			goto err;
		}
	}

	if (memcmp(&new_timings, &old_timings, sizeof(new_timings)) != 0) {
		if (display->set_timings)
			display->set_timings(display, &new_timings);

		/* sigh, bpp is not a setting of the display, but
		 * the overlay. */
		//def_display->panel->bpp = bpp;
	}

	if (display->set_update_mode && display->get_update_mode) {
		if (mode != display->get_update_mode(display))
			display->set_update_mode(display, mode);
	}

	if (display->enable_te && display->get_te) {
		if (te != display->get_te(display))
			display->enable_te(display, te);
	}

	if (display->set_rotate && display->get_rotate) {
		if (rot != display->get_rotate(display))
			display->set_rotate(display, rot);
	}

	if (display->set_mirror && display->get_mirror) {
		if (mir != display->get_mirror(display))
			display->set_mirror(display, mir);
	}

	if (display->set_tv_norm)
		display->set_tv_norm(display, new_norm);

	if (display->set_tv_type)
		display->set_tv_type(display, new_type);

	/* enable display after all settings */
	if (enable != (display->state != OMAP_DSS_DISPLAY_DISABLED)) {
		if (enable) {
			r = display->enable(display);
			if (r)
				dev_err(dev, "failed to enable display\n");
		} else {
			display->disable(display);
		}
	}

	r = count;
err:
	omapfb_unlock(fbdev);
	return r;
}
Ejemplo n.º 27
0
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_display *display = fb2display(fbi);

	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;
		enum omapfb_update_mode		update_mode;
		int test_num;
	} p;

	int r = 0;

	DBG("ioctl %x (%d)\n", cmd, cmd & 0xff);

	switch (cmd) {
	case OMAPFB_SYNC_GFX:
		if (!display || !display->sync) {
			/* DSS1 never returns an error here, so we neither */
			/*r = -EINVAL;*/
			break;
		}

		omapfb_lock(fbdev);
		r = display->sync(display);
		omapfb_unlock(fbdev);
		break;

	case OMAPFB_UPDATE_WINDOW_OLD:
		if (!display || !display->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:
		if (!display || !display->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:
		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_CROP_PLANE:
		if (copy_from_user(&p.plane_info, (void __user *)arg,
					sizeof(p.plane_info)))
			r = -EFAULT;
		else
			r = omapfb_crop_plane(fbi, &p.plane_info);
		break;

	case OMAPFB_QUERY_PLANE:
		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:
		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:
		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:
		if (!display) {
			r = -EINVAL;
			break;
		}

		p.caps.ctrl = display->caps;

		if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
			r = -EFAULT;
		break;

	case OMAPFB_SET_UPDATE_MODE:
		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:
		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;

	/* LCD and CTRL tests do the same thing for backward
	 * compatibility */
	case OMAPFB_LCD_TEST:
		if (get_user(p.test_num, (int __user *)arg)) {
			r = -EFAULT;
			break;
		}
		if (!display || !display->run_test) {
			r = -EINVAL;
			break;
		}

		r = display->run_test(display, p.test_num);

		break;

	case OMAPFB_CTRL_TEST:
		if (get_user(p.test_num, (int __user *)arg)) {
			r = -EFAULT;
			break;
		}
		if (!display || !display->run_test) {
			r = -EINVAL;
			break;
		}

		r = display->run_test(display, p.test_num);

		break;
	case OMAPFB_WAIT_FOR_VSYNC:
		return omapfb_wait_for_vsync(fbi);
		break;
        case OMAPFB_VRFB_ROTATE_CCW:
		ofbi->rotation_type = OMAPFB_ROT_VRFB;
  		ofbi->rotation = FB_ROTATE_CCW;
		set_fb_fix(fbi);
		omapfb_apply_changes(fbi, 0);
		
		break;
	default:
		DBG("ioctl unhandled\n");
		r = -EINVAL;
	}

	return r;
}
Ejemplo n.º 28
0
static int present_buffer(struct omap_display_buffer *buffer)
{
	struct omap_display_device *display = buffer->display;
	struct fb_info *framebuffer;
	struct omapfb_info *ofbi;
	struct omapfb2_device *fbdev;
	int i;
	int fb_idx;

	switch (display->id) {
	case OMAP_DISPID_PRIMARY:
		fb_idx = 0;
		break;
	case OMAP_DISPID_SECONDARY:
		fb_idx = 1;
		break;
	case OMAP_DISPID_TERTIARY:
		fb_idx = 2;
		break;
	case OMAP_DISPID_VIRTUAL:
	case OMAP_DISPID_BADSTATE:
	default:
		ERR_PRINT("Unable to handle display %i", display->id);
		BUG();
	}

	if (fb_idx < 0 || fb_idx >= num_registered_fb) {
		ERR_PRINT("Framebuffer %i doesn't exist for display '%s'",
			fb_idx, display->name);
		return 1;
	}

	framebuffer = registered_fb[fb_idx];
	ofbi = FB2OFB(framebuffer);
	fbdev = ofbi->fbdev;

	omapfb_lock(fbdev);

	/* Get the overlays attached to the framebuffer */
	for (i = 0; i < ofbi->num_overlays ; i++) {
		struct omap_dss_device *display = NULL;
		struct omap_dss_driver *driver = NULL;
		struct omap_overlay_manager *manager;
		struct omap_overlay *overlay;
		struct omap_overlay_info overlay_info;

		overlay = ofbi->overlays[i];
		manager = overlay->manager;
		overlay->get_overlay_info(overlay, &overlay_info);

		overlay_info.paddr = buffer->physical_addr;
		overlay_info.vaddr = (void *) buffer->virtual_addr;
		overlay->set_overlay_info(overlay, &overlay_info);

		if (manager) {
			manager->apply(manager);
			display = manager->device;
			driver = display ? display->driver : NULL;
		}

		if (dss_ovl_manually_updated(overlay)) {
			if (driver->sched_update)
				driver->sched_update(display, 0, 0,
							overlay_info.width,
							overlay_info.height);
			else if (driver->update)
				driver->update(display, 0, 0,
							overlay_info.width,
							overlay_info.height);
		}
	}

	omapfb_unlock(fbdev);

	return 0;
}
Ejemplo n.º 29
0
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);

	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_nolock(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_nolock(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;
		}

		r = display->manager->wait_for_vsync(display->manager);
		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: {
		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;

		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;
		u32 w, h;

		DBG("ioctl GET_DISPLAY_INFO\n");

		if (display == NULL) {
			r = -ENODEV;
			break;
		}

		get_fb_resolution(display, &xres, &yres);
		p.display_info.xres = xres;
		p.display_info.yres = yres;

		omapdss_display_get_dimensions(display, &w, &h);
		p.display_info.width = w;
		p.display_info.height = h;

		if (copy_to_user((void __user *)arg, &p.display_info,
					sizeof(p.display_info)))
			r = -EFAULT;
		break;
	}

	case OMAPFB_ENABLEVSYNC:
		if (get_user(p.crt, (__u32 __user *)arg)) {
			r = -EFAULT;
			break;
		}

		omapfb_lock(fbdev);
		fbdev->vsync_active = !!p.crt;

		if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
			if (p.crt)
				omapfb_enable_vsync(fbdev, display->channel,
					true);
			else
				omapfb_enable_vsync(fbdev, display->channel,
					false);
		}
		omapfb_unlock(fbdev);
		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;
}