int omap3epfb_set_region(struct fb_info *info, struct omap3epfb_area *p)
{
	struct omap3epfb_par *par = info->par;

	if ((p->index < 0) || (p->index >= EFFECT_ARRAY_SIZE))
		return -EINVAL;

	mutex_lock(&par->area_mutex);
	{
		// Set the correct flag for fast scan.
		if (p->effect_flags)
		{
			memcpy(&par->effect_array[p->index], p, sizeof(struct omap3epfb_area));
		}
		else
		{
			par->effect_array[p->index].effect_flags = 0;
		}
		update_effect(par, p->index);
	}
	mutex_unlock(&par->area_mutex);

	DEBUG_REGION(DEBUG_LEVEL4, &p->effect_area,"set effect=0x%02x region %d = ", p->effect_flags, p->index);

	return 0;
}
Ejemplo n.º 2
0
static bool batch_update(struct fb_info *info, struct omap3epfb_update_area *p)
{
	struct omap3epfb_par *par = info->par;

	// If EPD is disabled, do nothing
	if (par->disable_flags > 0)
	{
		DEBUG_REGION(DEBUG_LEVEL3, p,"update DISABLED = ");
		// Tell the caller not to update.
		return false;
	}

	// Check if the delayed full screen updates are enabled.
	if (!par->clear_delay)
	{
		DEBUG_REGION(DEBUG_LEVEL1, p,"   do = ");
		if (fast==1) {
			omap3epfb_update_screen(par->info, OMAP3EPFB_WVFID_VU, false);
		} else {
			omap3epfb_update_area(info, p);
		}
		return false;
	}

	// If this is not a fullscreen GC update, treat it as a normal update.
	if (!(rect_fullscreen(info, p) && p->wvfid == OMAP3EPFB_WVFID_GC))
	{
		// If we have a fullscreen batched, we do not need to update.
		if (!delayed_work_pending(&par->clear_work))
		{
			DEBUG_REGION(DEBUG_LEVEL1, p,"   do = ");
			if (fast==1) {
				omap3epfb_update_screen(par->info, OMAP3EPFB_WVFID_VU, false);
			} else {
				omap3epfb_update_area(info, p);
			}
		}
		else
		{
			DEBUG_REGION(DEBUG_LEVEL1, p,"   skip = ");
		}
		return false;
	}

	// We need to do fullscreen batching.
	if (par->user_debug & DEBUG_LEVEL1)
	{
		if (TIME_DELTA_MS(par->last_clear) < 1000)
			DEBUG_REGION(DEBUG_LEVEL1, p,"   req FULLSCREEN PREV %dms ago AUTO = ", TIME_DELTA_MS(par->last_clear));
		else
			DEBUG_REGION(DEBUG_LEVEL1, p,"   req FULLSCREEN = ");
	}
	omap3epfb_reqq_purge(par->info);
	cancel_delayed_work_sync(&par->clear_work);
	schedule_delayed_work(&par->clear_work, msecs_to_jiffies(par->clear_delay));
	par->last_clear = TIME_STAMP();
	return true;
}
int omap3epfb_fill_region(struct fb_info *info, struct omap3epfb_area *p)
{
	struct omap3epfb_par *par = info->par;

	if ((p->effect_area.threshold != OMAP3EPFB_THRESHOLD_BLACK) &&
	    (p->effect_area.threshold != OMAP3EPFB_THRESHOLD_WHITE))
		return -EINVAL;

	omap3epfb_reqq_purge(info);
	omap3epfb_update_area(info, &p->effect_area);

	DEBUG_REGION(DEBUG_LEVEL4, &p->effect_area,"  do fill = ");

	return 0;
}
int omap3epfb_get_region(struct fb_info *info, struct omap3epfb_area *p)
{
	struct omap3epfb_par *par = info->par;

	if ((p->index < 0) || (p->index >= EFFECT_ARRAY_SIZE))
		return -EINVAL;

	mutex_lock(&par->area_mutex);
	{
		memcpy(p, &par->effect_array[p->index], sizeof(struct omap3epfb_area));
	}
	mutex_unlock(&par->area_mutex);

	DEBUG_REGION(DEBUG_LEVEL4, &p->effect_area,"get effect=0x%02x region %d = ", p->effect_flags, p->index);

	return 0;
}
int user_update(struct fb_info *info, struct omap3epfb_update_area *p)
{
	struct omap3epfb_par *par = info->par;
	int percent = 0;
	u32 start_time = 0;

	// Get time of update
	start_time = ktime_to_ms();
	DEBUG_LOG(DEBUG_LEVEL4, "[%u ms] Start user_update\n", start_time);

	// If EPD is disabled, do nothing
	if (par->pgflip_refresh == 1)
	{
		// Tell the caller not to update.
		return 0;
	}

	// If EPD is disabled, do nothing
	if (par->disable_flags > 0)
	{
		DEBUG_REGION(DEBUG_LEVEL3, p,"update DISABLED = ");
		// Tell the caller not to update.
		return 0;
	}
	DEBUG_REGION(DEBUG_LEVEL5, p,"update REQUEST = ");
	
	if (waveform_select(info, p))
	{
		// Tell the caller not to update.
		return 0;
	}

	if (waveform_decompose(info, p))
	{
		// Tell the caller not to update.
		return 0;
	}

	// Calculate the percentage of the screen that needs an update.
	percent = ((rect_width(p) * rect_height(p) * 100)) /
		   ((info->var.xres-1) * (info->var.yres-1));

	// Check if we need to do a GC of the whole screen
	if ((par->refresh_percent > 0) && (percent >= par->refresh_percent))
	{
		// Check again if this needs to be flushing.
		if (buffer_difference_ge_threshold(info, par->refresh_percent))
		{
			DEBUG_REGION(DEBUG_LEVEL1, p,"process FULLSCREEN %d%% AUTO = ", percent);
			p->x0 = p->y0 = 0;
			p->x1 = info->var.xres-1;
			p->y1 = info->var.yres-1;
			p->wvfid = OMAP3EPFB_WVFID_GC;
			p->threshold = 0;
		}
		else
		{
			DEBUG_REGION(DEBUG_LEVEL1, p,"process false FULLSCREEN %d%% AUTO = ", percent);
		}
	}
	else
	{
		DEBUG_REGION(DEBUG_LEVEL1, p,"process AUTO = ");
	}

	batch_update(info, p);

	// Tell the caller not to update.
	return 0;
}
static int process_area(int index, struct fb_info *info, struct omap3epfb_area *area, struct omap3epfb_update_area *p)
{
	struct omap3epfb_par *par = info->par;
	int change = 0;

	if (!(area->effect_flags & (EFFECT_ONESHOT | EFFECT_ACTIVE | EFFECT_CLEAR)))
		return change;

	if (!rect_inside(&area->effect_area, p))
	{
		DEBUG_REGION(DEBUG_LEVEL5, p,"no match 0x%02x region %d = ", area->effect_flags, index);
		return change;
	}

	if (area->effect_flags & EFFECT_ONESHOT)
	{
		p->wvfid = area->effect_area.wvfid;
		p->threshold = area->effect_area.threshold;
		DEBUG_REGION(DEBUG_LEVEL2, p,"process ONESHOT region %d = ", index);
		if (area->effect_flags & EFFECT_REGION)
		{
			p->x0 = area->effect_area.x0;
			p->y0 = area->effect_area.y0;
			p->x1 = area->effect_area.x1;
			p->y1 = area->effect_area.y1;
		}
		par->effect_array[index].effect_flags = 0;
		change = 1;
	}
	else if (area->effect_flags & EFFECT_ACTIVE)
	{
		p->wvfid = area->effect_area.wvfid;
		p->threshold = area->effect_area.threshold;
		DEBUG_REGION(DEBUG_LEVEL2, p,"process ACTIVE region %d = ", index);
		change = 1;
		if (p->wvfid == OMAP3EPFB_WVFID_AUTO)
		{
			// Calculate the percentage of the screen that needs an update.
			int percent = ((rect_width(p) * rect_height(p) * 100)) /
			      ((info->var.xres-1) * (info->var.yres-1));

			// Check if we need to do a GC of the whole screen
			if ((par->refresh_percent > 0) && (percent >= par->refresh_percent))
			{
				DEBUG_REGION(DEBUG_LEVEL1, p,"process ACTIVE %d%% region %d = ", percent, index);
				p->x0 = p->y0 = 0;
				p->x1 = info->var.xres-1;
				p->y1 = info->var.yres-1;
				p->wvfid = OMAP3EPFB_WVFID_GC;
				p->threshold = 0;
			}
		}
		else
		{
			if (area->effect_flags & EFFECT_REGION)
			{
				p->x0 = area->effect_area.x0;
				p->y0 = area->effect_area.y0;
				p->x1 = area->effect_area.x1;
				p->y1 = area->effect_area.y1;
			}
		}
	}
	else if ((area->effect_flags & EFFECT_CLEAR) && rect_equal(&area->effect_area, p))
	{
		// Turn the next update of the effect area into a full page flushing update,
		// then clear the effect area.
		// This is used as a hint that a dialog is closing, then we forcing a full screen GC update.
		p->wvfid = area->effect_area.wvfid;
		p->threshold = area->effect_area.threshold;
		DEBUG_REGION(DEBUG_LEVEL2, p,"process RESET region %d = ", index);
		p->x0 = p->y0 = 0;
		p->x1 = info->var.xres-1;
		p->y1 = info->var.yres-1;
		p->wvfid = OMAP3EPFB_WVFID_GC;
		par->effect_array[index].effect_flags = 0;
		change = 1;
	}

	// Update the fast scan flags.
	update_effect(par, index);

	return change;
}