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

Commit f80de296 authored by Ray Zhang's avatar Ray Zhang Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: Refactor deterministic frame rate control



There are multiple branch conditions in current FRC design,
Simplify its design using finite state machine structure since
it's actually following pre-defined behaviors in different
states. All supported states are defined in frc_fsm_states.

Change-Id: I3bb1af548dfcf97134f11602607698fc92c9fe51
Signed-off-by: default avatarRay Zhang <rayz@codeaurora.org>
parent 24f27528
Loading
Loading
Loading
Loading
+0 −24
Original line number Diff line number Diff line
@@ -347,28 +347,6 @@ static void __check_cadence_pattern(struct mdss_dbg_frc_stat *frc_stat,
	}
}

static void __check_unexpected_delay(struct mdss_dbg_frc_stat *frc_stat,
	int s_idx, int e_idx)
{
	int i = 0;
	struct kickoff_samples *ks = &frc_stat->ks;

	pr_info("===== Check Unexpected Delay: =====\n");

	for (i = s_idx; i < e_idx; i++) {
		struct cadence *p_info = &frc_stat->cadence_info[i];
		struct kick_stat *kickoff = &ks->samples[p_info->kickoff_idx];

		if (kickoff->remain + kickoff->vsync
			!= kickoff->frc_info.last_vsync_cnt)
			pr_info("\tUnexpected Delay: timestamp=%lld, vsync=%d\n",
				kickoff->frc_info.cur_frc.timestamp,
				kickoff->vsync);
	}

	pr_info("===== Check Unexpected Delay End =====\n");
}

static int __is_cadence_check_supported(struct mdss_dbg_frc_stat *frc_stat)
{
	int cadence = frc_stat->cadence_id;
@@ -494,8 +472,6 @@ static void mdss_frc_dump_debug_stat(struct mdss_dbg_frc *frc_debug)
	__dump_frc_samples(frc_stat, cnt);

	if (__is_cadence_check_supported(frc_stat)) {
		__check_unexpected_delay(frc_stat, 0, cnt);

		pr_info("===== Check Cadence Pattern: =====\n");
		__check_cadence_pattern(frc_stat, 0, cnt);
		pr_info("===== Check Cadence Pattern End =====\n");
+85 −2
Original line number Diff line number Diff line
@@ -425,7 +425,6 @@ struct mdss_mdp_frc_cadence_calc {
};

struct mdss_mdp_frc_info {
	bool enable;
	u32 cadence_id; /* patterns such as 22/23/23223 */
	u32 display_fp1000s;
	u32 last_vsync_cnt; /* vsync when we kicked off last frame */
@@ -440,6 +439,84 @@ struct mdss_mdp_frc_info {
	struct mdss_mdp_frc_seq_gen gen;
};

/*
 * FSM used in deterministic frame rate control:
 *
 *                +----------------+                      +----------------+
 *                | +------------+ |    too many drops    | +------------+ |
 *       +--------> |  INIT      | +----------------------> |   DISABLE  | |
 *       |        | +------------+ <-----------+          | +------------+ |
 *       |        +----------------+           |          +----------------+
 *       |           |        |                |
 *       |           |        |                | change
 *       |      frame|        |change          +----------------+
 *       |           |        |                                 |
 *       |           |        |                                 |
 *       |        +--v--------+----+                      +-----+----------+
 * change|        |                |      not supported   |                |
 *       |        | CADENCE_DETECT +---------------------->    FREE_RUN    |
 *       |        |                |                      |                |
 *       |        +-------+--------+                      +----------------+
 *       |                |
 *       |                |
 *       |                |cadence detected
 *       |                |
 *       |                |
 *       |        +-------v--------+             +----------------------------+
 *       |        |                |             |Events:                     |
 *       +--------+  SEQ_MATCH     |             |  1. change: some changes   |
 *       |        |                |             |  might change cadence like |
 *       |        +-------+--------+             |  video/display fps.        |
 *       |                |                      |  2. frame: video frame with|
 *       |                |sequence matched      |  correct FRC info.         |
 *       |                |                      |  3. in other states than   |
 *       |        +-------v--------+             |  INIT frame event doesn't  |
 *       |        |                |             |  make any state change.    |
 *       |        |                |             +----------------------------+
 *       +--------+   READY        |
 *                |                |
 *                +----------------+
 */
enum mdss_mdp_frc_state_type {
	FRC_STATE_INIT = 0, /* INIT state waiting for frames */
	FRC_STATE_CADENCE_DETECT, /* state to detect cadence ID */
	FRC_STATE_SEQ_MATCH, /* state to find start pos in cadence sequence */
	FRC_STATE_FREERUN, /* state has no extra repeat but might be changed */
	FRC_STATE_READY, /* state ready to do FRC */
	FRC_STATE_DISABLE, /* state in which FRC is disabled */
	FRC_STATE_MAX,
};

struct mdss_mdp_frc_fsm;

struct mdss_mdp_frc_fsm_ops {
	/* preprocess incoming FRC info like checking fps changes */
	void (*pre_frc)(struct mdss_mdp_frc_fsm *frc_fsm, void *arg);
	/* deterministic frame rate control like delaying frame's display */
	void (*do_frc)(struct mdss_mdp_frc_fsm *frc_fsm, void *arg);
	/* post-operations after FRC like saving past info */
	void (*post_frc)(struct mdss_mdp_frc_fsm *frc_fsm, void *arg);
};

struct mdss_mdp_frc_fsm_cbs {
	/* callback used once updating FRC FSM's state */
	void (*update_state_cb)(struct mdss_mdp_frc_fsm *frc_fsm);
};

struct mdss_mdp_frc_fsm_state {
	char *name; /* debug name of current state */
	enum mdss_mdp_frc_state_type state; /* current state type */
	struct mdss_mdp_frc_fsm_ops ops; /* operations of curent state */
};

struct mdss_mdp_frc_fsm {
	bool enable; /* whether FRC is running */
	struct mdss_mdp_frc_fsm_state state; /* current state */
	struct mdss_mdp_frc_fsm_state to_state; /* state to set */
	struct mdss_mdp_frc_fsm_cbs cbs;
	struct mdss_mdp_frc_info frc_info;
};

struct mdss_mdp_ctl {
	u32 num;
	char __iomem *base;
@@ -929,7 +1006,7 @@ struct mdss_overlay_private {
	bool allow_kickoff;

	/* video frame info used by deterministic frame rate control */
	struct mdss_mdp_frc_info *frc_info;
	struct mdss_mdp_frc_fsm *frc_fsm;
};

struct mdss_mdp_set_ot_params {
@@ -1842,6 +1919,12 @@ void mdss_mdp_disable_hw_irq(struct mdss_data_type *mdata);

void mdss_mdp_set_supported_formats(struct mdss_data_type *mdata);

void mdss_mdp_frc_fsm_init_state(struct mdss_mdp_frc_fsm *frc_fsm);
void mdss_mdp_frc_fsm_change_state(struct mdss_mdp_frc_fsm *frc_fsm,
	enum mdss_mdp_frc_state_type state,
	void (*cb)(struct mdss_mdp_frc_fsm *frc_fsm));
void mdss_mdp_frc_fsm_update_state(struct mdss_mdp_frc_fsm *frc_fsm);

#ifdef CONFIG_FB_MSM_MDP_NONE
struct mdss_data_type *mdss_mdp_get_mdata(void)
{
+9 −7
Original line number Diff line number Diff line
@@ -1940,12 +1940,14 @@ static void __parse_frc_info(struct mdss_overlay_private *mdp5_data,
	struct mdp_frc_info *input_frc)
{
	struct mdss_mdp_ctl *ctl = mdp5_data->ctl;
	struct mdss_mdp_frc_info *frc_info = mdp5_data->frc_info;
	struct mdss_mdp_frc_fsm *frc_fsm = mdp5_data->frc_fsm;

	if (input_frc->flags & MDP_VIDEO_FRC_ENABLE) {
		if (!frc_info->enable) {
			/* init frc_info when first entry */
			memset(frc_info, 0, sizeof(struct mdss_mdp_frc_info));
		struct mdss_mdp_frc_info *frc_info = &frc_fsm->frc_info;

		if (!frc_fsm->enable) {
			/* init frc_fsm when first entry */
			mdss_mdp_frc_fsm_init_state(frc_fsm);
			/* keep vsync on when FRC is enabled */
			ctl->ops.add_vsync_handler(ctl,
					&ctl->frc_vsync_handler);
@@ -1953,14 +1955,14 @@ static void __parse_frc_info(struct mdss_overlay_private *mdp5_data,

		frc_info->cur_frc.frame_cnt = input_frc->frame_cnt;
		frc_info->cur_frc.timestamp = input_frc->timestamp;
	} else if (frc_info->enable) {
	} else if (frc_fsm->enable) {
		/* remove vsync handler when FRC is disabled */
		ctl->ops.remove_vsync_handler(ctl, &ctl->frc_vsync_handler);
	}

	frc_info->enable = input_frc->flags & MDP_VIDEO_FRC_ENABLE;
	frc_fsm->enable = input_frc->flags & MDP_VIDEO_FRC_ENABLE;

	pr_debug("frc_enable=%d\n", frc_info->enable);
	pr_debug("frc_enable=%d\n", frc_fsm->enable);
}

/*
+402 −230

File changed.

Preview size limit exceeded, changes collapsed.