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

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

Merge "drm: msm: improve early splash mechanism"

parents 43fb4adb c96659a8
Loading
Loading
Loading
Loading
+2 −11
Original line number Diff line number Diff line
@@ -572,8 +572,6 @@ void sde_connector_complete_commit(struct drm_connector *connector)
{
	struct drm_device *dev;
	struct msm_drm_private *priv;
	struct sde_connector *c_conn;
	struct sde_kms *sde_kms;

	if (!connector) {
		SDE_ERROR("invalid connector\n");
@@ -582,7 +580,6 @@ void sde_connector_complete_commit(struct drm_connector *connector)

	dev = connector->dev;
	priv = dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);

	/* signal connector's retire fence */
	sde_fence_signal(&to_sde_connector(connector)->retire_fence, 0);
@@ -590,14 +587,8 @@ void sde_connector_complete_commit(struct drm_connector *connector)
	/* after first vsync comes,
	 * early splash resource should start to be released.
	 */
	if (sde_splash_get_lk_complete_status(&sde_kms->splash_info)) {
		c_conn = to_sde_connector(connector);

		sde_splash_clean_up_free_resource(priv->kms,
						&priv->phandle,
						c_conn->connector_type,
						c_conn->display);
	}
	if (sde_splash_get_lk_complete_status(priv->kms))
		sde_splash_free_resource(priv->kms, &priv->phandle);

}

+19 −2
Original line number Diff line number Diff line
@@ -304,6 +304,8 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
	struct sde_crtc_mixer *mixer = sde_crtc->mixers;
	struct sde_hw_ctl *ctl;
	struct sde_hw_mixer *lm;
	struct sde_splash_info *sinfo;
	struct sde_kms *sde_kms = _sde_crtc_get_kms(crtc);

	int i;

@@ -314,6 +316,17 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
		return;
	}

	if (!sde_kms) {
		SDE_ERROR("invalid sde_kms\n");
		return;
	}

	sinfo = &sde_kms->splash_info;
	if (!sinfo) {
		SDE_ERROR("invalid splash info\n");
		return;
	}

	for (i = 0; i < sde_crtc->num_mixers; i++) {
		if (!mixer[i].hw_lm || !mixer[i].hw_ctl) {
			SDE_ERROR("invalid lm or ctl assigned to mixer\n");
@@ -323,7 +336,10 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
		mixer[i].flush_mask = 0;
		if (mixer[i].hw_ctl->ops.clear_all_blendstages)
			mixer[i].hw_ctl->ops.clear_all_blendstages(
					mixer[i].hw_ctl);
					mixer[i].hw_ctl,
					sinfo->handoff,
					sinfo->reserved_pipe_info,
					MAX_BLOCKS);
	}

	/* initialize stage cfg */
@@ -350,7 +366,8 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
			mixer[i].flush_mask);

		ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
			&sde_crtc->stage_cfg, i);
			&sde_crtc->stage_cfg, i,
			sinfo->handoff, sinfo->reserved_pipe_info, MAX_BLOCKS);
	}
}

+96 −4
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -258,6 +258,35 @@ static inline int sde_hw_ctl_get_bitmask_cdm(struct sde_hw_ctl *ctx,
	return 0;
}

static inline int sde_hw_ctl_get_splash_mixercfg(const u32 *resv_pipes,
						u32 length)
{
	int i = 0;
	u32 mixercfg = 0;

	for (i = 0; i < length; i++) {
		/* LK's splash VIG layer always stays on top */
		switch (resv_pipes[i]) {
		case SSPP_VIG0:
			mixercfg |= 0x7 << 0;
			break;
		case SSPP_VIG1:
			mixercfg |= 0x7 << 3;
			break;
		case SSPP_VIG2:
			mixercfg |= 0x7 << 6;
			break;
		case SSPP_VIG3:
			mixercfg |= 0x7 << 26;
			break;
		default:
			break;
		}
	}

	return mixercfg;
}

static u32 sde_hw_ctl_poll_reset_status(struct sde_hw_ctl *ctx, u32 count)
{
	struct sde_hw_blk_reg_map *c = &ctx->hw;
@@ -312,15 +341,29 @@ static int sde_hw_ctl_wait_reset_status(struct sde_hw_ctl *ctx)
	return 0;
}

static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx)
static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx,
		bool handoff, const u32 *resv_pipes, u32 resv_pipes_length)
{
	struct sde_hw_blk_reg_map *c = &ctx->hw;
	int i;

	for (i = 0; i < ctx->mixer_count; i++) {
		int mixer_id = ctx->mixer_hw_caps[i].id;
		u32 mixercfg = 0;

		/*
		 * if bootloaer still has early RVC running, mixer status
		 * can't be direcly cleared.
		 */
		if (handoff) {
			mixercfg =
				sde_hw_ctl_get_splash_mixercfg(resv_pipes,
						resv_pipes_length);

			mixercfg &= SDE_REG_READ(c, CTL_LAYER(mixer_id));
		}

		SDE_REG_WRITE(c, CTL_LAYER(mixer_id), 0);
		SDE_REG_WRITE(c, CTL_LAYER(mixer_id), mixercfg);
		SDE_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);
		SDE_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);
		SDE_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);
@@ -328,7 +371,8 @@ static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx)
}

static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
	enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg, u32 index)
	enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg, u32 index,
	bool handoff, const u32 *resv_pipes, u32 resv_pipes_length)
{
	struct sde_hw_blk_reg_map *c = &ctx->hw;
	u32 mixercfg, mixercfg_ext, mix, ext, mixercfg_ext2;
@@ -353,6 +397,20 @@ static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
	mixercfg_ext = 0;
	mixercfg_ext2 = 0;

	/*
	 * if bootloader still have RVC running, its mixer stauts
	 * should be updated to kernel's mixer setup.
	 */
	if (handoff) {
		mixercfg =
			sde_hw_ctl_get_splash_mixercfg(resv_pipes,
						resv_pipes_length);

		mixercfg &= SDE_REG_READ(c, CTL_LAYER(lm));
		mixercfg |= BIT(24);
		stages--;
	}

	for (i = 0; i <= stages; i++) {
		/* overflow to ext register if 'i + 1 > 7' */
		mix = (i + 1) & 0x7;
@@ -458,6 +516,38 @@ static void sde_hw_ctl_intf_cfg(struct sde_hw_ctl *ctx,
	SDE_REG_WRITE(c, CTL_TOP, intf_cfg);
}

static inline u32 sde_hw_ctl_read_ctl_top_for_splash(struct sde_hw_ctl *ctx)
{
	struct sde_hw_blk_reg_map *c;
	u32 ctl_top;

	if (!ctx) {
		pr_err("Invalid ctx\n");
		return 0;
	}

	c = &ctx->hw;
	ctl_top = SDE_REG_READ(c, CTL_TOP);
	return ctl_top;
}

static inline u32 sde_hw_ctl_read_ctl_layers_for_splash(struct sde_hw_ctl *ctx,
							int index)
{
	struct sde_hw_blk_reg_map *c;
	u32 ctl_top;

	if (!ctx) {
		pr_err("Invalid ctx\n");
		return 0;
	}

	c = &ctx->hw;
	ctl_top = SDE_REG_READ(c, CTL_LAYER(index));

	return ctl_top;
}

static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
		unsigned long cap)
{
@@ -478,6 +568,8 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
	ops->get_bitmask_intf = sde_hw_ctl_get_bitmask_intf;
	ops->get_bitmask_cdm = sde_hw_ctl_get_bitmask_cdm;
	ops->get_bitmask_wb = sde_hw_ctl_get_bitmask_wb;
	ops->read_ctl_top_for_splash = sde_hw_ctl_read_ctl_top_for_splash;
	ops->read_ctl_layers_for_splash = sde_hw_ctl_read_ctl_layers_for_splash;
};

struct sde_hw_ctl *sde_hw_ctl_init(enum sde_ctl idx,
+26 −3
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -146,17 +146,40 @@ struct sde_hw_ctl_ops {
	/**
	 * Set all blend stages to disabled
	 * @ctx       : ctl path ctx pointer
	 * @handoff   : handoff flag
	 * @resv_pipes  : reserved pipes in DT
	 * @resv_pipes_length:    array size of array reserved_pipes
	 */
	void (*clear_all_blendstages)(struct sde_hw_ctl *ctx);
	void (*clear_all_blendstages)(struct sde_hw_ctl *ctx,
		bool handoff, const u32 *resv_pipes, u32 resv_pipes_length);

	/**
	 * Configure layer mixer to pipe configuration
	 * @ctx       : ctl path ctx pointer
	 * @lm        : layer mixer enumeration
	 * @cfg       : blend stage configuration
	 * @handoff   : handoff flag
	 * @resv_pipes  : reserved pipes in DT
	 * @resv_pipes_length:   array size of array reserved_pipes
	 */
	void (*setup_blendstage)(struct sde_hw_ctl *ctx,
		enum sde_lm lm, struct sde_hw_stage_cfg *cfg, u32 index);
		enum sde_lm lm, struct sde_hw_stage_cfg *cfg, u32 index,
		bool handoff, const u32 *resv_pipes, u32 resv_pipes_length);

	/**
	 * read CTL_TOP register value for splash case
	 * @ctx       : ctl path ctx pointer
	 * @Return    : CTL top register value
	 */
	u32 (*read_ctl_top_for_splash)(struct sde_hw_ctl *ctx);

	/**
	 * read CTL layers register value for splash case
	 * @ctx       : ctl path ctx pointer
	 * @index     : layer index for this ctl path
	 * @Return    : CTL layers register value
	 */
	u32 (*read_ctl_layers_for_splash)(struct sde_hw_ctl *ctx, int index);
};

/**
+3 −2
Original line number Diff line number Diff line
@@ -343,8 +343,9 @@ static void sde_kms_prepare_commit(struct msm_kms *kms,
	struct drm_device *dev = sde_kms->dev;
	struct msm_drm_private *priv = dev->dev_private;

	if (sde_kms->splash_info.handoff)
		sde_splash_clean_up_exit_lk(kms);
	if (sde_kms->splash_info.handoff &&
		sde_kms->splash_info.display_splash_enabled)
		sde_splash_lk_stop_splash(kms);
	else
		sde_power_resource_enable(&priv->phandle,
				sde_kms->core_client, true);
Loading