/**
 * Limit the number of cores used in some "easy" and impossible cases
 */
static int limit_blits(int n_split, struct b2r2_blt_req *user_req)
{
	if (n_split <= 1)
		return n_split;

	if (user_req->dst_rect.width < 24 && user_req->dst_rect.height < 24)
		return 1;

	if (user_req->src_rect.width < n_split &&
			user_req->src_rect.height < n_split)
		return 1;

	/*
	 * Handle macroblock formats with one
	 * core for now since there seems to be some bug
	 * related to macroblock access patterns
	 */
	if (is_mb_fmt(user_req->src_img.fmt))
		return 1;

	return n_split;
}
/**
 * Split a request rectangle on available cores
 */
static int b2r2_blt_split_request(struct b2r2_blt_data *blt_data,
		struct b2r2_blt_req *user_req,
		struct b2r2_blt_request **split_requests,
		struct b2r2_control_instance **ctl,
		int *n_split)
{
	int sstep_x, sstep_y, dstep_x, dstep_y;
	int dstart_x, dstart_y;
	int bstart_x, bstart_y;
	int dpos_x, dpos_y;
	int bpos_x, bpos_y;
	int dso_x = 1;
	int dso_y = 1;
	int sf_x, sf_y;
	int i;
	int srw, srh;
	int drw, drh;
	bool ssplit_x = true;
	bool dsplit_x = true;
	enum b2r2_blt_transform transform;
	bool is_rotation = false;
	bool is_scaling = false;
	bool bg_blend = false;
	u32 core_mask = 0;

	srw = user_req->src_rect.width;
	srh = user_req->src_rect.height;
	drw = user_req->dst_rect.width;
	drh = user_req->dst_rect.height;
	transform = user_req->transform;

	/* Early exit in the basic cases */
	if (*n_split == 0) {
		return -ENOSYS;
	} else if (*n_split == 1 ||
			(srw < *n_split && srh < *n_split) ||
			(drw < *n_split && drh < *n_split) ||
			is_mb_fmt(user_req->src_img.fmt)) {
		/*
		 * Handle macroblock formats with one
		 * core for now since there seems to be some bug
		 * related to macroblock access patterns
		 */
		memcpy(&split_requests[0]->user_req,
				user_req,
				sizeof(*user_req));
		split_requests[0]->core_mask =
				(1 << split_requests[0]->instance->control_id);
		*n_split = 1;
		return 0;
	}

	/*
	 * TODO: fix the load balancing algorithm
	 */

	is_rotation = (transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) != 0;

	/* Check for scaling */
	if (is_rotation) {
		is_scaling = (user_req->src_rect.width !=
				user_req->dst_rect.height) ||
			(user_req->src_rect.height !=
				user_req->dst_rect.width);
	} else {
		is_scaling = (user_req->src_rect.width !=
				user_req->dst_rect.width) ||
			(user_req->src_rect.height !=
				user_req->dst_rect.height);
	}

	is_scaling = is_scaling ||
			is_scaling_fmt(user_req->src_img.fmt) ||
			is_scaling_fmt(user_req->dst_img.fmt);

	bg_blend = ((user_req->flags & B2R2_BLT_FLAG_BG_BLEND) != 0);

	/*
	 * Split the request
	 */

	b2r2_log_info(b2r2_blt->dev, "%s: In (t:0x%08X, f:0x%08X):\n"
		"\tsrc_rect x:%d, y:%d, w:%d, h:%d src fmt:0x%x\n"
		"\tdst_rect x:%d, y:%d, w:%d, h:%d dst fmt:0x%x\n",
		__func__,
		user_req->transform,
		user_req->flags,
		user_req->src_rect.x,
		user_req->src_rect.y,
		user_req->src_rect.width,
		user_req->src_rect.height,
		user_req->src_img.fmt,
		user_req->dst_rect.x,
		user_req->dst_rect.y,
		user_req->dst_rect.width,
		user_req->dst_rect.height,
		user_req->dst_img.fmt);

	/*
	 * TODO: We need sub pixel precision here,
	 * or a better way to split rects
	 */
	dstart_x = user_req->dst_rect.x;
	dstart_y = user_req->dst_rect.y;
	if (bg_blend) {
		bstart_x = user_req->bg_rect.x;
		bstart_y = user_req->bg_rect.y;
	}

	if (srw && srh) {
		if ((srw < srh) && !is_scaling) {
			ssplit_x = false;
			sstep_y = srh / *n_split;
			/* Round up */
			if (srh % (*n_split))
				sstep_y++;

			if (srh > 16)
				sstep_y = ((sstep_y + 16) >> 4) << 4;

			if (transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
				sf_y = (drw << 10) / srh;
				dstep_x = (sf_y * sstep_y) >> 10;
			} else {