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

Commit 5148a8f2 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: mdp: adapt frame idle timeout to input events"

parents c61d684e 35d775ad
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -482,6 +482,7 @@ static void __mdss_fb_idle_notify_work(struct work_struct *work)
	pr_debug("Idle timeout %dms expired!\n", mfd->idle_time);
	if (mfd->idle_time)
		sysfs_notify(&mfd->fbi->dev->kobj, NULL, "idle_notify");
	mfd->idle_state = MDSS_FB_IDLE;
}

static ssize_t mdss_fb_get_idle_time(struct device *dev,
@@ -1053,9 +1054,13 @@ static int mdss_fb_probe(struct platform_device *pdev)
	 * Register with input driver for a callback for command mode panels.
	 * When there is an input event, mdp clocks will be turned on to reduce
	 * latency when a frame update happens.
	 * Video mode panels are not handled today because clocks are always on.
	 * For video mode panels, idle timeout will be delayed so that userspace
	 * does not get an idle event while new frames are expected. In case of
	 * an idle event, user space tries to fall back to GPU composition which
	 * can lead to increased load when there are new frames.
	 */
	if (mfd->panel_info->type == MIPI_CMD_PANEL)
	if ((mfd->panel_info->type == MIPI_CMD_PANEL) ||
	    (mfd->panel_info->type == MIPI_VIDEO_PANEL))
		if (mdss_fb_register_input_handler(mfd))
			pr_err("failed to register input handler\n");

@@ -2733,6 +2738,8 @@ static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
					msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT)))
			pr_debug("fb%d: start idle delayed work\n",
					mfd->index);

		mfd->idle_state = MDSS_FB_NOT_IDLE;
		break;
	case MDP_NOTIFY_FRAME_READY:
		if (sync_pt_data->async_wait_fences &&
@@ -2749,6 +2756,7 @@ static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
					mfd->index);
		if (ret == -ETIME)
			ret = NOTIFY_BAD;
		mfd->idle_state = MDSS_FB_IDLE_TIMER_RUNNING;
		break;
	case MDP_NOTIFY_FRAME_FLUSHED:
		pr_debug("%s: frame flushed\n", sync_pt_data->fence_name);
+13 −0
Original line number Diff line number Diff line
@@ -141,6 +141,18 @@ enum dyn_mode_switch_state {
	MDSS_MDP_WAIT_FOR_COMMIT,
};

/**
 * enum mdss_fb_idle_state - idle states based on frame updates
 * @MDSS_FB_NOT_IDLE: Frame updates have started
 * @MDSS_FB_IDLE_TIMER_RUNNING: Idle timer has been kicked
 * @MDSS_FB_IDLE: Currently idle
 */
enum mdss_fb_idle_state {
	MDSS_FB_NOT_IDLE,
	MDSS_FB_IDLE_TIMER_RUNNING,
	MDSS_FB_IDLE
};

struct disp_info_type_suspend {
	int op_enable;
	int panel_power_state;
@@ -257,6 +269,7 @@ struct msm_fb_data_type {
	struct fb_info *fbi;

	int idle_time;
	u32 idle_state;
	struct delayed_work idle_notify_work;

	bool validate_pending;
+39 −0
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@
/* Poll time to do recovery during active region */
#define POLL_TIME_USEC_FOR_LN_CNT 500

/* Filter out input events for 1 vsync time after receiving an input event*/
#define INPUT_EVENT_HANDLER_DELAY_USECS 16000

#define MDP_INTR_MASK_INTF_VSYNC(intf_num) \
	(1 << (2 * (intf_num - MDSS_MDP_INTF0) + MDSS_MDP_IRQ_INTF_VSYNC))

@@ -1549,6 +1552,41 @@ void mdss_mdp_switch_to_cmd_mode(struct mdss_mdp_ctl *ctl, int prep)
	mdss_bus_bandwidth_ctrl(false);
}

static int mdss_mdp_video_early_wake_up(struct mdss_mdp_ctl *ctl)
{
	u64 curr_time;

	curr_time = ktime_to_us(ktime_get());

	if ((curr_time - ctl->last_input_time) <
			INPUT_EVENT_HANDLER_DELAY_USECS)
		return 0;
	ctl->last_input_time = curr_time;

	/*
	 * If the idle timer is running when input event happens, the timeout
	 * will be delayed by idle_time again to ensure user space does not get
	 * an idle event when new frames are expected.
	 *
	 * It would be nice to have this logic in mdss_fb.c itself by
	 * implementing a new frame notification event. But input event handler
	 * is called from interrupt context and scheduling a work item adds a
	 * lot of latency rendering the input events useless in preventing the
	 * idle time out.
	 */
	if (ctl->mfd->idle_state == MDSS_FB_IDLE_TIMER_RUNNING) {
		if (ctl->mfd->idle_time)
			mod_delayed_work(system_wq, &ctl->mfd->idle_notify_work,
					 msecs_to_jiffies(ctl->mfd->idle_time));
		pr_debug("Delayed idle time\n");
	} else {
		pr_debug("Nothing to done for this state (%d)\n",
			 ctl->mfd->idle_state);
	}

	return 0;
}

int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl)
{
	int intfs_num, ret = 0;
@@ -1567,6 +1605,7 @@ int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl)
	ctl->ops.add_vsync_handler = mdss_mdp_video_add_vsync_handler;
	ctl->ops.remove_vsync_handler = mdss_mdp_video_remove_vsync_handler;
	ctl->ops.config_fps_fnc = mdss_mdp_video_config_fps;
	ctl->ops.early_wake_up_fnc = mdss_mdp_video_early_wake_up;

	return 0;
}