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

Commit d145dd78 authored by Stephane Viau's avatar Stephane Viau Committed by Rob Clark
Browse files

drm/msm/mdp5: Enhance operation mode for pipeline configuration



DSI and WB interfaces need a more complex pipeline configuration
than the current mdp5_ctl_set_intf().

For example, memory output connections need to be selected for
WB. Interface mode (Video vs. Command modes) also need to be
configured for DSI.

This change takes care of configuring the whole pipeline as far
as operation mode goes. DSI and WB interfaces will be added
later.

v2: rename macro to mdp5_cfg_intf_is_virtual() [pointed by Archit]

Signed-off-by: default avatarStephane Viau <sviau@codeaurora.org>
[Remove temp bisectability hack -Rob]
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent a13cebab
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -84,6 +84,10 @@ const struct mdp5_cfg_hw *mdp5_cfg_get_hw_config(struct mdp5_cfg_handler *cfg_hn
struct mdp5_cfg *mdp5_cfg_get_config(struct mdp5_cfg_handler *cfg_hnd);
int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_hnd);

#define mdp5_cfg_intf_is_virtual(intf_type) ({	\
	typeof(intf_type) __val = (intf_type);	\
	(__val) >= INTF_VIRTUAL ? true : false; })

struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
		uint32_t major, uint32_t minor);
void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_hnd);
+4 −35
Original line number Diff line number Diff line
@@ -611,48 +611,17 @@ void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
}

/* set interface for routing crtc->encoder: */
void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf,
		enum mdp5_intf intf_id)
void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf)
{
	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
	struct mdp5_kms *mdp5_kms = get_kms(crtc);
	uint32_t intf_sel;
	unsigned long flags;
	int lm = mdp5_crtc_get_lm(crtc);

	/* now that we know what irq's we want: */
	mdp5_crtc->err.irqmask = intf2err(intf);
	mdp5_crtc->vblank.irqmask = intf2vblank(intf);
	mdp5_crtc->err.irqmask = intf2err(intf->num);
	mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);
	mdp_irq_update(&mdp5_kms->base);

	spin_lock_irqsave(&mdp5_kms->resource_lock, flags);
	intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL);

	switch (intf) {
	case 0:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF0__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF0(intf_id);
		break;
	case 1:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF1__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF1(intf_id);
		break;
	case 2:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF2__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF2(intf_id);
		break;
	case 3:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF3__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF3(intf_id);
		break;
	default:
		BUG();
		break;
	}

	mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, intf_sel);
	spin_unlock_irqrestore(&mdp5_kms->resource_lock, flags);

	DBG("%s: intf_sel=%08x", mdp5_crtc->name, intf_sel);
	mdp5_ctl_set_intf(mdp5_crtc->ctl, intf);
}

+81 −10
Original line number Diff line number Diff line
@@ -33,6 +33,16 @@
 * requested by the client (in mdp5_crtc_mode_set()).
 */

struct op_mode {
	struct mdp5_interface intf;
	/*
	 * TODO: add a state variable to control the pipeline
	 *
	 * eg: WB interface needs both buffer addresses to be committed +
	 * output buffers ready to be written into, before we can START.
	 */
};

struct mdp5_ctl {
	struct mdp5_ctl_manager *ctlm;

@@ -41,8 +51,8 @@ struct mdp5_ctl {
	/* whether this CTL has been allocated or not: */
	bool busy;

	/* memory output connection (@see mdp5_ctl_mode): */
	u32 mode;
	/* Operation Mode Configuration for the Pipeline */
	struct op_mode pipeline;

	/* REG_MDP5_CTL_*(<id>) registers access info + lock: */
	spinlock_t hw_lock;
@@ -94,19 +104,81 @@ u32 ctl_read(struct mdp5_ctl *ctl, u32 reg)
	return mdp5_read(mdp5_kms, reg);
}

static void set_display_intf(struct mdp5_kms *mdp5_kms,
		struct mdp5_interface *intf)
{
	unsigned long flags;
	u32 intf_sel;

	spin_lock_irqsave(&mdp5_kms->resource_lock, flags);
	intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL);

	switch (intf->num) {
	case 0:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF0__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF0(intf->type);
		break;
	case 1:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF1__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF1(intf->type);
		break;
	case 2:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF2__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF2(intf->type);
		break;
	case 3:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF3__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF3(intf->type);
		break;
	default:
		BUG();
		break;
	}

	mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, intf_sel);
	spin_unlock_irqrestore(&mdp5_kms->resource_lock, flags);
}

int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, int intf)
static void set_ctl_op(struct mdp5_ctl *ctl, struct mdp5_interface *intf)
{
	unsigned long flags;
	static const enum mdp5_intfnum intfnum[] = {
			INTF0, INTF1, INTF2, INTF3,
	};
	u32 ctl_op = 0;

	if (!mdp5_cfg_intf_is_virtual(intf->type))
		ctl_op |= MDP5_CTL_OP_INTF_NUM(INTF0 + intf->num);

	switch (intf->type) {
	case INTF_DSI:
		if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
			ctl_op |= MDP5_CTL_OP_CMD_MODE;
		break;

	case INTF_WB:
		if (intf->mode == MDP5_INTF_WB_MODE_LINE)
			ctl_op |= MDP5_CTL_OP_MODE(MODE_WB_2_LINE);
		break;

	default:
		break;
	}

	spin_lock_irqsave(&ctl->hw_lock, flags);
	ctl_write(ctl, REG_MDP5_CTL_OP(ctl->id),
			MDP5_CTL_OP_MODE(ctl->mode) |
			MDP5_CTL_OP_INTF_NUM(intfnum[intf]));
	ctl_write(ctl, REG_MDP5_CTL_OP(ctl->id), ctl_op);
	spin_unlock_irqrestore(&ctl->hw_lock, flags);
}

int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, struct mdp5_interface *intf)
{
	struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
	struct mdp5_kms *mdp5_kms = get_kms(ctl_mgr);

	memcpy(&ctl->pipeline.intf, intf, sizeof(*intf));

	/* Virtual interfaces need not set a display intf (e.g.: Writeback) */
	if (!mdp5_cfg_intf_is_virtual(intf->type))
		set_display_intf(mdp5_kms, intf);

	set_ctl_op(ctl, intf);

	return 0;
}
@@ -303,7 +375,6 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
		}
		ctl->ctlm = ctl_mgr;
		ctl->id = c;
		ctl->mode = MODE_NONE;
		ctl->reg_offset = ctl_cfg->base[c];
		ctl->flush_mask = MDP5_CTL_FLUSH_CTL;
		ctl->busy = false;
+2 −1
Original line number Diff line number Diff line
@@ -34,7 +34,8 @@ void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctlm);
 */
struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctlm, struct drm_crtc *crtc);

int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, int intf);
struct mdp5_interface;
int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, struct mdp5_interface *intf);

int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, bool enable);

+14 −15
Original line number Diff line number Diff line
@@ -23,8 +23,7 @@

struct mdp5_encoder {
	struct drm_encoder base;
	int intf;
	enum mdp5_intf intf_id;
	struct mdp5_interface intf;
	spinlock_t intf_lock;	/* protect REG_MDP5_INTF_* registers */
	bool enabled;
	uint32_t bsc;
@@ -126,7 +125,7 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
	struct mdp5_kms *mdp5_kms = get_kms(encoder);
	struct drm_device *dev = encoder->dev;
	struct drm_connector *connector;
	int intf = mdp5_encoder->intf;
	int intf = mdp5_encoder->intf.num;
	uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
	uint32_t display_v_start, display_v_end;
	uint32_t hsync_start_x, hsync_end_x;
@@ -188,7 +187,7 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
	 * DISPLAY_V_START = (VBP * HCYCLE) + HBP
	 * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
	 */
	if (mdp5_encoder->intf_id == INTF_eDP) {
	if (mdp5_encoder->intf.type == INTF_eDP) {
		display_v_start += mode->htotal - mode->hsync_start;
		display_v_end -= mode->hsync_start - mode->hdisplay;
	}
@@ -224,14 +223,16 @@ static void mdp5_encoder_disable(struct drm_encoder *encoder)
{
	struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
	struct mdp5_kms *mdp5_kms = get_kms(encoder);
	int intf = mdp5_encoder->intf;
	int lm = mdp5_crtc_get_lm(encoder->crtc);
	struct mdp5_interface *intf = &mdp5_encoder->intf;
	int intfn = mdp5_encoder->intf.num;
	unsigned long flags;

	if (WARN_ON(!mdp5_encoder->enabled))
		return;

	spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
	mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0);
	mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 0);
	spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);

	/*
@@ -242,7 +243,7 @@ static void mdp5_encoder_disable(struct drm_encoder *encoder)
	 * the settings changes for the new modeset (like new
	 * scanout buffer) don't latch properly..
	 */
	mdp_irq_wait(&mdp5_kms->base, intf2vblank(intf));
	mdp_irq_wait(&mdp5_kms->base, intf2vblank(lm, intf));

	bs_set(mdp5_encoder, 0);

@@ -253,18 +254,17 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder)
{
	struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
	struct mdp5_kms *mdp5_kms = get_kms(encoder);
	int intf = mdp5_encoder->intf;
	int intfn = mdp5_encoder->intf.num;
	unsigned long flags;

	if (WARN_ON(mdp5_encoder->enabled))
		return;

	mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf,
			mdp5_encoder->intf_id);
	mdp5_crtc_set_intf(encoder->crtc, &mdp5_encoder->intf);

	bs_set(mdp5_encoder, 1);
	spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
	mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1);
	mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1);
	spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);

	mdp5_encoder->enabled = true;
@@ -278,8 +278,8 @@ static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
};

/* initialize encoder */
struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf,
		enum mdp5_intf intf_id)
struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
				struct mdp5_interface *intf)
{
	struct drm_encoder *encoder = NULL;
	struct mdp5_encoder *mdp5_encoder;
@@ -291,8 +291,7 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf,
		goto fail;
	}

	mdp5_encoder->intf = intf;
	mdp5_encoder->intf_id = intf_id;
	memcpy(&mdp5_encoder->intf, intf, sizeof(mdp5_encoder->intf));
	encoder = &mdp5_encoder->base;

	spin_lock_init(&mdp5_encoder->intf_lock);
Loading