Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb8e7141 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mdss: restructure rotator code and add mutex for rotator api"

parents c5b6680d 59ca4806
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -483,7 +483,15 @@ void mdss_mdp_clk_ctrl(int enable, int isr);
struct mdss_data_type *mdss_mdp_get_mdata(void);

int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
			       struct mdp_overlay *req,
			       struct mdss_mdp_format_params *fmt);
int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en);
int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
			     struct mdss_mdp_data *data,
			     struct msmfb_data *planes,
			     int num_planes,
			     u32 flags);
int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata,
		u32 *offsets,  u32 count);
int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
@@ -610,6 +618,7 @@ void mdss_mdp_data_calc_offset(struct mdss_mdp_data *data, u16 x, u16 y,
struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data);
int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data);
u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase);
void mdss_mdp_intersect_rect(struct mdss_mdp_img_rect *res_rect,
+8 −141
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ static int mdss_mdp_overlay_get(struct msm_fb_data_type *mfd,
	return 0;
}

static int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
			       struct mdp_overlay *req,
			       struct mdss_mdp_format_params *fmt)
{
@@ -249,85 +249,6 @@ static int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
	return 0;
}

static int mdss_mdp_overlay_rotator_setup(struct msm_fb_data_type *mfd,
					  struct mdp_overlay *req)
{
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_mdp_rotator_session *rot;
	struct mdss_mdp_format_params *fmt;
	int ret = 0;
	u32 bwc_enabled;

	pr_debug("rot ctl=%u req id=%x\n", mdp5_data->ctl->num, req->id);

	fmt = mdss_mdp_get_format_params(req->src.format);
	if (!fmt) {
		pr_err("invalid rot format %d\n", req->src.format);
		return -EINVAL;
	}

	ret = mdss_mdp_overlay_req_check(mfd, req, fmt);
	if (ret)
		return ret;

	if (req->id == MSMFB_NEW_REQUEST) {
		rot = mdss_mdp_rotator_session_alloc();
		rot->pid = current->tgid;
		list_add(&rot->list, &mdp5_data->rot_proc_list);

		if (!rot) {
			pr_err("unable to allocate rotator session\n");
			return -ENOMEM;
		}
	} else if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
		rot = mdss_mdp_rotator_session_get(req->id);

		if (!rot) {
			pr_err("rotator session=%x not found\n", req->id);
			return -ENODEV;
		}
	} else {
		pr_err("invalid rotator session id=%x\n", req->id);
		return -EINVAL;
	}

	/* keep only flags of interest to rotator */
	rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD |
				   MDP_SECURE_OVERLAY_SESSION);

	bwc_enabled = req->flags & MDP_BWC_EN;
	if (bwc_enabled  &&  !mdp5_data->mdata->has_bwc) {
		pr_err("BWC is not supported in MDP version %x\n",
			mdp5_data->mdata->mdp_rev);
		rot->bwc_mode = 0;
	} else {
		rot->bwc_mode = bwc_enabled ? 1 : 0;
	}
	rot->format = fmt->format;
	rot->img_width = req->src.width;
	rot->img_height = req->src.height;
	rot->src_rect.x = req->src_rect.x;
	rot->src_rect.y = req->src_rect.y;
	rot->src_rect.w = req->src_rect.w;
	rot->src_rect.h = req->src_rect.h;

	if (req->flags & MDP_DEINTERLACE) {
		rot->flags |= MDP_DEINTERLACE;
		rot->src_rect.h /= 2;
		rot->src_rect.y = DIV_ROUND_UP(rot->src_rect.y, 2);
	}

	ret = mdss_mdp_rotator_setup(rot);
	if (ret == 0) {
		req->id = rot->session_id;
	} else {
		pr_err("Unable to setup rotator session\n");
		mdss_mdp_rotator_release(rot);
	}

	return ret;
}

static int __mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe)
{
	struct mdss_data_type *mdata = pipe->mixer->ctl->mdata;
@@ -688,7 +609,7 @@ static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
	}

	if (req->flags & MDSS_MDP_ROT_ONLY) {
		ret = mdss_mdp_overlay_rotator_setup(mfd, req);
		ret = mdss_mdp_rotator_setup(mfd, req);
	} else if (req->src.format == MDP_RGB_BORDERFILL) {
		req->id = BORDERFILL_NDX;
	} else {
@@ -707,7 +628,7 @@ static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
	return ret;
}

static inline int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
					   struct mdss_mdp_data *data,
					   struct msmfb_data *planes,
					   int num_planes,
@@ -737,7 +658,7 @@ static inline int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
	return rc;
}

static inline int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
{
	int i;
	for (i = 0; i < data->num_planes && data->p[i].len; i++)
@@ -1180,17 +1101,7 @@ static int mdss_mdp_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
	pr_debug("unset ndx=%x\n", ndx);

	if (ndx & MDSS_MDP_ROT_SESSION_MASK) {
		struct mdss_mdp_rotator_session *rot;
		rot = mdss_mdp_rotator_session_get(ndx);
		if (rot) {
			mdss_mdp_overlay_free_buf(&rot->src_buf);
			mdss_mdp_overlay_free_buf(&rot->dst_buf);

			rot->pid = 0;
			if (!list_empty(&rot->list))
				list_del_init(&rot->list);
			ret = mdss_mdp_rotator_release(rot);
		}
		ret = mdss_mdp_rotator_unset(ndx);
	} else {
		ret = mdss_mdp_overlay_release(mfd, ndx);
	}
@@ -1271,50 +1182,6 @@ static int mdss_mdp_overlay_play_wait(struct msm_fb_data_type *mfd,
	return ret;
}

static int mdss_mdp_overlay_rotate(struct msm_fb_data_type *mfd,
				   struct msmfb_overlay_data *req)
{
	struct mdss_mdp_rotator_session *rot;
	int ret;
	u32 flgs;

	rot = mdss_mdp_rotator_session_get(req->id);
	if (!rot) {
		pr_err("invalid session id=%x\n", req->id);
		return -ENOENT;
	}

	flgs = rot->flags & MDP_SECURE_OVERLAY_SESSION;

	ret = mdss_mdp_rotator_busy_wait_ex(rot);
	if (ret) {
		pr_err("rotator busy wait error\n");
		return ret;
	}

	mdss_mdp_overlay_free_buf(&rot->src_buf);
	ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
	if (ret) {
		pr_err("src_data pmem error\n");
		return ret;
	}

	mdss_mdp_overlay_free_buf(&rot->dst_buf);
	ret = mdss_mdp_overlay_get_buf(mfd, &rot->dst_buf,
			&req->dst_data, 1, flgs);
	if (ret) {
		pr_err("dst_data pmem error\n");
		goto dst_buf_fail;
	}

	ret = mdss_mdp_rotator_queue(rot);
	if (ret)
		pr_err("rotator queue error session id=%x\n", req->id);

dst_buf_fail:
	return ret;
}

static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
				  struct msmfb_overlay_data *req)
{
@@ -1409,7 +1276,7 @@ static int mdss_mdp_overlay_play(struct msm_fb_data_type *mfd,
	if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
		mdss_mdp_overlay_force_dma_cleanup(mfd_to_mdata(mfd));

		ret = mdss_mdp_overlay_rotate(mfd, req);
		ret = mdss_mdp_rotator_play(mfd, req);
	} else if (req->id == BORDERFILL_NDX) {
		pr_debug("borderfill enable\n");
		mdp5_data->borderfill_enable = true;
+173 −27
Original line number Diff line number Diff line
@@ -37,12 +37,11 @@ static int mdss_mdp_rotator_queue_helper(struct mdss_mdp_rotator_session *rot);
static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create(
			struct mdss_mdp_rotator_session *rot);

struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
static struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
{
	struct mdss_mdp_rotator_session *rot;
	int i;

	mutex_lock(&rotator_lock);
	for (i = 0; i < MAX_ROTATOR_SESSIONS; i++) {
		rot = &rotator_session[i];
		if (rot->ref_cnt == 0) {
@@ -52,16 +51,15 @@ struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
			break;
		}
	}
	mutex_unlock(&rotator_lock);
	if (i == MAX_ROTATOR_SESSIONS) {
		pr_err("max rotator sessions reached\n");
		return NULL;
	}

	return rot;
}

struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id)
static inline struct mdss_mdp_rotator_session
*mdss_mdp_rotator_session_get(u32 session_id)
{
	struct mdss_mdp_rotator_session *rot;
	u32 ndx;
@@ -113,16 +111,15 @@ static struct mdss_mdp_pipe *mdss_mdp_rotator_pipe_alloc(void)

static int mdss_mdp_rotator_busy_wait(struct mdss_mdp_rotator_session *rot)
{
	struct mdss_mdp_pipe *rot_pipe = NULL;
	struct mdss_mdp_ctl *ctl = NULL;

	rot_pipe = rot->pipe;
	if (!rot_pipe)
	mutex_lock(&rot->lock);
	if (!rot->pipe || !rot->pipe->mixer || !rot->pipe->mixer->ctl) {
		mutex_unlock(&rot->lock);
		return -ENODEV;
	}

	ctl = rot_pipe->mixer->ctl;
	mutex_lock(&rot->lock);
	if (rot->busy) {
		struct mdss_mdp_ctl *ctl = rot->pipe->mixer->ctl;
		mdss_mdp_display_wait4comp(ctl);
		rot->busy = false;
		if (ctl->shared_lock)
@@ -277,16 +274,24 @@ static void mdss_mdp_rotator_commit_wq_handler(struct work_struct *work)

	rot = container_of(work, struct mdss_mdp_rotator_session, commit_work);

	mutex_lock(&rotator_lock);
	ret = mdss_mdp_rotator_queue_helper(rot);

	atomic_inc(&rot->rot_sync_pt_data->commit_cnt);

	ret = mdss_mdp_rotator_queue_helper(rot);
	if (ret)
	if (ret) {
		pr_err("rotator queue failed\n");
		mutex_unlock(&rotator_lock);
		return;
	}

	if (rot->rot_sync_pt_data)
		mdss_fb_signal_timeline(rot->rot_sync_pt_data);
	else
		pr_err("rot_sync_pt_data is NULL\n");

	mutex_unlock(&rotator_lock);
}

static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create(
@@ -318,7 +323,7 @@ static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create(
	return sync_pt_data;
}

int mdss_mdp_rotator_busy_wait_ex(struct mdss_mdp_rotator_session *rot)
static int mdss_mdp_rotator_busy_wait_ex(struct mdss_mdp_rotator_session *rot)
{

	struct mdss_mdp_rotator_session *tmp;
@@ -337,20 +342,12 @@ static int mdss_mdp_rotator_queue_helper(struct mdss_mdp_rotator_session *rot)
	int ret;
	struct mdss_mdp_rotator_session *tmp;

	ret = mutex_lock_interruptible(&rotator_lock);
	if (ret) {
		pr_err("mutex lock on rotator_lock failed\n");
		return ret;
	}

	pr_debug("rotator session=%x start\n", rot->session_id);

	for (ret = 0, tmp = rot; ret == 0 && tmp; tmp = tmp->next)
		ret = mdss_mdp_rotator_queue_sub(tmp,
				&rot->src_buf, &rot->dst_buf);

	mutex_unlock(&rotator_lock);

	if (ret) {
		pr_err("rotation failed %d for rot=%d\n", ret, rot->session_id);
		return ret;
@@ -362,7 +359,7 @@ static int mdss_mdp_rotator_queue_helper(struct mdss_mdp_rotator_session *rot)
	return ret;
}

int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot)
static int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot)
{
	int ret = 0;

@@ -376,10 +373,80 @@ int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot)
	return ret;
}

int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot)
int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd,
			   struct mdp_overlay *req)
{
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_mdp_rotator_session *rot = NULL;
	struct mdss_mdp_format_params *fmt;
	u32 bwc_enabled;
	int ret = 0;

	mutex_lock(&rotator_lock);

	fmt = mdss_mdp_get_format_params(req->src.format);
	if (!fmt) {
		pr_err("invalid rot format %d\n", req->src.format);
		ret = -EINVAL;
		goto rot_err;
	}

	ret = mdss_mdp_overlay_req_check(mfd, req, fmt);
	if (ret)
		goto rot_err;

	if (req->id == MSMFB_NEW_REQUEST) {
		rot = mdss_mdp_rotator_session_alloc();
		rot->pid = current->tgid;
		list_add(&rot->list, &mdp5_data->rot_proc_list);

		if (!rot) {
			pr_err("unable to allocate rotator session\n");
			ret = -ENOMEM;
			goto rot_err;
		}
	} else if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
		rot = mdss_mdp_rotator_session_get(req->id);

		if (!rot) {
			pr_err("rotator session=%x not found\n", req->id);
			ret = -ENODEV;
			goto rot_err;
		}
	} else {
		pr_err("invalid rotator session id=%x\n", req->id);
		ret = -EINVAL;
		goto rot_err;
	}

	/* keep only flags of interest to rotator */
	rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD |
				   MDP_SECURE_OVERLAY_SESSION);

	bwc_enabled = req->flags & MDP_BWC_EN;
	if (bwc_enabled  &&  !mdp5_data->mdata->has_bwc) {
		pr_err("BWC is not supported in MDP version %x\n",
			mdp5_data->mdata->mdp_rev);
		rot->bwc_mode = 0;
	} else {
		rot->bwc_mode = bwc_enabled ? 1 : 0;
	}
	rot->format = fmt->format;
	rot->img_width = req->src.width;
	rot->img_height = req->src.height;
	rot->src_rect.x = req->src_rect.x;
	rot->src_rect.y = req->src_rect.y;
	rot->src_rect.w = req->src_rect.w;
	rot->src_rect.h = req->src_rect.h;

	if (req->flags & MDP_DEINTERLACE) {
		rot->flags |= MDP_DEINTERLACE;
		rot->src_rect.h /= 2;
		rot->src_rect.y = DIV_ROUND_UP(rot->src_rect.y, 2);
	}

	rot->dst = rot->src_rect;

	/*
	 * by default, rotator output should be placed directly on
	 * output buffer address without any offset.
@@ -396,7 +463,8 @@ int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot)

		if (rot->bwc_mode) {
			pr_err("Unable to do split rotation with bwc set\n");
			return -EINVAL;
			ret = -EINVAL;
			goto rot_err;
		}

		width = rot->src_rect.w;
@@ -406,14 +474,16 @@ int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot)

		if (width > (MAX_MIXER_WIDTH * 2)) {
			pr_err("unsupported source width %d\n", width);
			return -EOVERFLOW;
			ret = -EOVERFLOW;
			goto rot_err;
		}

		if (!rot->next) {
			tmp = mdss_mdp_rotator_session_alloc();
			if (!tmp) {
				pr_err("unable to allocate rot dual session\n");
				return -ENOMEM;
				ret = -ENOMEM;
				goto rot_err;
			}
			rot->next = tmp;
		}
@@ -461,7 +531,16 @@ int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot)

	rot->params_changed++;

	return 0;
	req->id = rot->session_id;

 rot_err:
	mutex_unlock(&rotator_lock);
	if (ret) {
		pr_err("Unable to setup rotator session\n");
		if (rot)
			mdss_mdp_rotator_release(rot);
	}
	return ret;
}

static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot)
@@ -537,3 +616,70 @@ int mdss_mdp_rotator_release_all(void)

	return 0;
}

int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
			    struct msmfb_overlay_data *req)
{
	struct mdss_mdp_rotator_session *rot;
	int ret;
	u32 flgs;

	mutex_lock(&rotator_lock);
	rot = mdss_mdp_rotator_session_get(req->id);
	if (!rot) {
		pr_err("invalid session id=%x\n", req->id);
		ret = -ENOENT;
		goto dst_buf_fail;
	}

	flgs = rot->flags & MDP_SECURE_OVERLAY_SESSION;

	ret = mdss_mdp_rotator_busy_wait_ex(rot);
	if (ret) {
		pr_err("rotator busy wait error\n");
		goto dst_buf_fail;
	}

	mdss_mdp_overlay_free_buf(&rot->src_buf);
	ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
	if (ret) {
		pr_err("src_data pmem error\n");
		goto dst_buf_fail;
	}

	mdss_mdp_overlay_free_buf(&rot->dst_buf);
	ret = mdss_mdp_overlay_get_buf(mfd, &rot->dst_buf,
			&req->dst_data, 1, flgs);
	if (ret) {
		pr_err("dst_data pmem error\n");
		goto dst_buf_fail;
	}

	ret = mdss_mdp_rotator_queue(rot);

	if (ret)
		pr_err("rotator queue error session id=%x\n", req->id);

dst_buf_fail:
	mutex_unlock(&rotator_lock);
	return ret;
}

int mdss_mdp_rotator_unset(int ndx)
{
	struct mdss_mdp_rotator_session *rot;
	int ret = 0;
	mutex_lock(&rotator_lock);
	rot = mdss_mdp_rotator_session_get(ndx);
	if (rot) {
		mdss_mdp_overlay_free_buf(&rot->src_buf);
		mdss_mdp_overlay_free_buf(&rot->dst_buf);

		rot->pid = 0;
		if (!list_empty(&rot->list))
			list_del_init(&rot->list);
		ret = mdss_mdp_rotator_finish(rot);
	}
	mutex_unlock(&rotator_lock);
	return ret;
}
+5 −6
Original line number Diff line number Diff line
@@ -75,14 +75,13 @@ static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format, u8 in_rot90)
	}
}

struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void);
struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id);

int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot);
int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot);
int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd,
			   struct mdp_overlay *req);
int mdss_mdp_rotator_release(struct mdss_mdp_rotator_session *rot);
int mdss_mdp_rotator_release_all(void);
int mdss_mdp_rotator_busy_wait_ex(struct mdss_mdp_rotator_session *rot);
struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_get(
	struct msm_fb_data_type *mfd, const struct mdp_buf_sync *buf_sync);
int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
			    struct msmfb_overlay_data *req);
int mdss_mdp_rotator_unset(int ndx);
#endif /* MDSS_MDP_ROTATOR_H */