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

Commit 59ca4806 authored by Huaibin Yang's avatar Huaibin Yang
Browse files

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



The rotator data structure should be maintained in the rotator file
and rotator api calls should be following current ioctls, namely,
rotator_setup follows overlay_set, rotator_play follows overlay_play,
and rotator_unset follows overlay_unset. In this way, rotator code is
modulized and data is isolated easily by adding proper locking.

CRs-fixed: 563019
Change-Id: I3aa0db57d65cf9ae88c7e7cbccb3fa73a25e5902
Signed-off-by: default avatarHuaibin Yang <huaibiny@codeaurora.org>
parent 759f5a97
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -473,7 +473,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);
@@ -600,6 +608,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;
@@ -682,7 +603,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 {
@@ -701,7 +622,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,
@@ -731,7 +652,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++)
@@ -1174,17 +1095,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);
	}
@@ -1265,50 +1176,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)
{
@@ -1403,7 +1270,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 */