Commit b6057cda authored by Jeykumar Sankaran's avatar Jeykumar Sankaran Committed by Rob Clark
Browse files

drm/msm/dpu: move hw_inf encoder baseclass



Both video and command physical encoders will have
a hw interface assigned to it. So there is really no
need to track the hw block in specific encoder subclass.

Signed-off-by: default avatarJeykumar Sankaran <jsanka@codeaurora.org>
Signed-off-by: default avatarSean Paul <seanpaul@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/1550107156-17625-2-git-send-email-jsanka@codeaurora.org


Signed-off-by: default avatarRob Clark <robdclark@chromium.org>
parent f98baa31
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -200,6 +200,7 @@ struct dpu_encoder_irq {
 * @hw_mdptop:		Hardware interface to the top registers
 * @hw_ctl:		Hardware interface to the ctl registers
 * @hw_pp:		Hardware interface to the ping pong registers
 * @hw_intf:		Hardware interface to the intf registers
 * @dpu_kms:		Pointer to the dpu_kms top level
 * @cached_mode:	DRM mode cached at mode_set time, acted on in enable
 * @enabled:		Whether the encoder has enabled and running a mode
@@ -228,6 +229,7 @@ struct dpu_encoder_phys {
	struct dpu_hw_mdp *hw_mdptop;
	struct dpu_hw_ctl *hw_ctl;
	struct dpu_hw_pingpong *hw_pp;
	struct dpu_hw_intf *hw_intf;
	struct dpu_kms *dpu_kms;
	struct drm_display_mode cached_mode;
	enum dpu_enc_split_role split_role;
@@ -254,12 +256,10 @@ static inline int dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
 * struct dpu_encoder_phys_vid - sub-class of dpu_encoder_phys to handle video
 *	mode specific operations
 * @base:	Baseclass physical encoder structure
 * @hw_intf:	Hardware interface to the intf registers
 * @timing_params: Current timing parameter
 */
struct dpu_encoder_phys_vid {
	struct dpu_encoder_phys base;
	struct dpu_hw_intf *hw_intf;
	struct intf_timing_params timing_params;
};

+50 −75
Original line number Diff line number Diff line
@@ -18,14 +18,14 @@
#include "dpu_trace.h"

#define DPU_DEBUG_VIDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \
		(e) && (e)->base.parent ? \
		(e)->base.parent->base.id : -1, \
		(e) && (e)->parent ? \
		(e)->parent->base.id : -1, \
		(e) && (e)->hw_intf ? \
		(e)->hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)

#define DPU_ERROR_VIDENC(e, fmt, ...) DPU_ERROR("enc%d intf%d " fmt, \
		(e) && (e)->base.parent ? \
		(e)->base.parent->base.id : -1, \
		(e) && (e)->parent ? \
		(e)->parent->base.id : -1, \
		(e) && (e)->hw_intf ? \
		(e)->hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)

@@ -44,7 +44,7 @@ static bool dpu_encoder_phys_vid_is_master(
}

static void drm_mode_to_intf_timing_params(
		const struct dpu_encoder_phys_vid *vid_enc,
		const struct dpu_encoder_phys *phys_enc,
		const struct drm_display_mode *mode,
		struct intf_timing_params *timing)
{
@@ -92,7 +92,7 @@ static void drm_mode_to_intf_timing_params(
	timing->hsync_skew = mode->hskew;

	/* DSI controller cannot handle active-low sync signals. */
	if (vid_enc->hw_intf->cap->type == INTF_DSI) {
	if (phys_enc->hw_intf->cap->type == INTF_DSI) {
		timing->hsync_polarity = 0;
		timing->vsync_polarity = 0;
	}
@@ -143,11 +143,11 @@ static u32 get_vertical_total(const struct intf_timing_params *timing)
 * lines based on the chip worst case latencies.
 */
static u32 programmable_fetch_get_num_lines(
		struct dpu_encoder_phys_vid *vid_enc,
		struct dpu_encoder_phys *phys_enc,
		const struct intf_timing_params *timing)
{
	u32 worst_case_needed_lines =
	    vid_enc->hw_intf->cap->prog_fetch_lines_worst_case;
	    phys_enc->hw_intf->cap->prog_fetch_lines_worst_case;
	u32 start_of_frame_lines =
	    timing->v_back_porch + timing->vsync_pulse_width;
	u32 needed_vfp_lines = worst_case_needed_lines - start_of_frame_lines;
@@ -155,26 +155,26 @@ static u32 programmable_fetch_get_num_lines(

	/* Fetch must be outside active lines, otherwise undefined. */
	if (start_of_frame_lines >= worst_case_needed_lines) {
		DPU_DEBUG_VIDENC(vid_enc,
		DPU_DEBUG_VIDENC(phys_enc,
				"prog fetch is not needed, large vbp+vsw\n");
		actual_vfp_lines = 0;
	} else if (timing->v_front_porch < needed_vfp_lines) {
		/* Warn fetch needed, but not enough porch in panel config */
		pr_warn_once
			("low vbp+vfp may lead to perf issues in some cases\n");
		DPU_DEBUG_VIDENC(vid_enc,
		DPU_DEBUG_VIDENC(phys_enc,
				"less vfp than fetch req, using entire vfp\n");
		actual_vfp_lines = timing->v_front_porch;
	} else {
		DPU_DEBUG_VIDENC(vid_enc, "room in vfp for needed prefetch\n");
		DPU_DEBUG_VIDENC(phys_enc, "room in vfp for needed prefetch\n");
		actual_vfp_lines = needed_vfp_lines;
	}

	DPU_DEBUG_VIDENC(vid_enc,
	DPU_DEBUG_VIDENC(phys_enc,
		"v_front_porch %u v_back_porch %u vsync_pulse_width %u\n",
		timing->v_front_porch, timing->v_back_porch,
		timing->vsync_pulse_width);
	DPU_DEBUG_VIDENC(vid_enc,
	DPU_DEBUG_VIDENC(phys_enc,
		"wc_lines %u needed_vfp_lines %u actual_vfp_lines %u\n",
		worst_case_needed_lines, needed_vfp_lines, actual_vfp_lines);

@@ -194,8 +194,6 @@ static u32 programmable_fetch_get_num_lines(
static void programmable_fetch_config(struct dpu_encoder_phys *phys_enc,
				      const struct intf_timing_params *timing)
{
	struct dpu_encoder_phys_vid *vid_enc =
		to_dpu_encoder_phys_vid(phys_enc);
	struct intf_prog_fetch f = { 0 };
	u32 vfp_fetch_lines = 0;
	u32 horiz_total = 0;
@@ -203,10 +201,10 @@ static void programmable_fetch_config(struct dpu_encoder_phys *phys_enc,
	u32 vfp_fetch_start_vsync_counter = 0;
	unsigned long lock_flags;

	if (WARN_ON_ONCE(!vid_enc->hw_intf->ops.setup_prg_fetch))
	if (WARN_ON_ONCE(!phys_enc->hw_intf->ops.setup_prg_fetch))
		return;

	vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, timing);
	vfp_fetch_lines = programmable_fetch_get_num_lines(phys_enc, timing);
	if (vfp_fetch_lines) {
		vert_total = get_vertical_total(timing);
		horiz_total = get_horizontal_total(timing);
@@ -216,12 +214,12 @@ static void programmable_fetch_config(struct dpu_encoder_phys *phys_enc,
		f.fetch_start = vfp_fetch_start_vsync_counter;
	}

	DPU_DEBUG_VIDENC(vid_enc,
	DPU_DEBUG_VIDENC(phys_enc,
		"vfp_fetch_lines %u vfp_fetch_start_vsync_counter %u\n",
		vfp_fetch_lines, vfp_fetch_start_vsync_counter);

	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
	vid_enc->hw_intf->ops.setup_prg_fetch(vid_enc->hw_intf, &f);
	phys_enc->hw_intf->ops.setup_prg_fetch(phys_enc->hw_intf, &f);
	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
}

@@ -231,7 +229,7 @@ static bool dpu_encoder_phys_vid_mode_fixup(
		struct drm_display_mode *adj_mode)
{
	if (phys_enc)
		DPU_DEBUG_VIDENC(to_dpu_encoder_phys_vid(phys_enc), "\n");
		DPU_DEBUG_VIDENC(phys_enc, "\n");

	/*
	 * Modifying mode has consequences when the mode comes back to us
@@ -257,12 +255,12 @@ static void dpu_encoder_phys_vid_setup_timing_engine(

	mode = phys_enc->cached_mode;
	vid_enc = to_dpu_encoder_phys_vid(phys_enc);
	if (!vid_enc->hw_intf->ops.setup_timing_gen) {
	if (!phys_enc->hw_intf->ops.setup_timing_gen) {
		DPU_ERROR("timing engine setup is not supported\n");
		return;
	}

	DPU_DEBUG_VIDENC(vid_enc, "enabling mode:\n");
	DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
	drm_mode_debug_printmodeline(&mode);

	if (phys_enc->split_role != ENC_ROLE_SOLO) {
@@ -271,25 +269,25 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
		mode.hsync_start >>= 1;
		mode.hsync_end >>= 1;

		DPU_DEBUG_VIDENC(vid_enc,
		DPU_DEBUG_VIDENC(phys_enc,
			"split_role %d, halve horizontal %d %d %d %d\n",
			phys_enc->split_role,
			mode.hdisplay, mode.htotal,
			mode.hsync_start, mode.hsync_end);
	}

	drm_mode_to_intf_timing_params(vid_enc, &mode, &timing_params);
	drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);

	fmt = dpu_get_dpu_format(fmt_fourcc);
	DPU_DEBUG_VIDENC(vid_enc, "fmt_fourcc 0x%X\n", fmt_fourcc);
	DPU_DEBUG_VIDENC(phys_enc, "fmt_fourcc 0x%X\n", fmt_fourcc);

	intf_cfg.intf = vid_enc->hw_intf->idx;
	intf_cfg.intf = phys_enc->hw_intf->idx;
	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID;
	intf_cfg.stream_sel = 0; /* Don't care value for video mode */
	intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);

	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
	vid_enc->hw_intf->ops.setup_timing_gen(vid_enc->hw_intf,
	phys_enc->hw_intf->ops.setup_timing_gen(phys_enc->hw_intf,
			&timing_params, fmt);
	phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
@@ -396,19 +394,15 @@ static void dpu_encoder_phys_vid_mode_set(
		struct drm_display_mode *mode,
		struct drm_display_mode *adj_mode)
{
	struct dpu_encoder_phys_vid *vid_enc;

	if (!phys_enc || !phys_enc->dpu_kms) {
		DPU_ERROR("invalid encoder/kms\n");
		return;
	}

	vid_enc = to_dpu_encoder_phys_vid(phys_enc);

	if (adj_mode) {
		phys_enc->cached_mode = *adj_mode;
		drm_mode_debug_printmodeline(adj_mode);
		DPU_DEBUG_VIDENC(vid_enc, "caching mode:\n");
		DPU_DEBUG_VIDENC(phys_enc, "caching mode:\n");
	}

	_dpu_encoder_phys_vid_setup_irq_hw_idx(phys_enc);
@@ -419,7 +413,6 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
		bool enable)
{
	int ret = 0;
	struct dpu_encoder_phys_vid *vid_enc;
	int refcount;

	if (!phys_enc) {
@@ -428,7 +421,6 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
	}

	refcount = atomic_read(&phys_enc->vblank_refcount);
	vid_enc = to_dpu_encoder_phys_vid(phys_enc);

	/* Slave encoders don't report vblank */
	if (!dpu_encoder_phys_vid_is_master(phys_enc))
@@ -453,7 +445,7 @@ end:
	if (ret) {
		DRM_ERROR("failed: id:%u intf:%d ret:%d enable:%d refcnt:%d\n",
			  DRMID(phys_enc->parent),
			  vid_enc->hw_intf->idx - INTF_0, ret, enable,
			  phys_enc->hw_intf->idx - INTF_0, ret, enable,
			  refcount);
	}
	return ret;
@@ -462,7 +454,6 @@ end:
static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
{
	struct msm_drm_private *priv;
	struct dpu_encoder_phys_vid *vid_enc;
	struct dpu_rm_hw_iter iter;
	struct dpu_hw_ctl *ctl;
	u32 flush_mask = 0;
@@ -474,7 +465,6 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
	}
	priv = phys_enc->parent->dev->dev_private;

	vid_enc = to_dpu_encoder_phys_vid(phys_enc);
	ctl = phys_enc->hw_ctl;

	dpu_rm_init_hw_iter(&iter, phys_enc->parent->base.id, DPU_HW_BLK_INTF);
@@ -482,22 +472,22 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
		struct dpu_hw_intf *hw_intf = (struct dpu_hw_intf *)iter.hw;

		if (hw_intf->idx == phys_enc->intf_idx) {
			vid_enc->hw_intf = hw_intf;
			phys_enc->hw_intf = hw_intf;
			break;
		}
	}

	if (!vid_enc->hw_intf) {
	if (!phys_enc->hw_intf) {
		DPU_ERROR("hw_intf not assigned\n");
		return;
	}

	DPU_DEBUG_VIDENC(vid_enc, "\n");
	DPU_DEBUG_VIDENC(phys_enc, "\n");

	if (WARN_ON(!vid_enc->hw_intf->ops.enable_timing))
	if (WARN_ON(!phys_enc->hw_intf->ops.enable_timing))
		return;

	dpu_encoder_helper_split_config(phys_enc, vid_enc->hw_intf->idx);
	dpu_encoder_helper_split_config(phys_enc, phys_enc->hw_intf->idx);

	dpu_encoder_phys_vid_setup_timing_engine(phys_enc);

@@ -510,11 +500,12 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
		!dpu_encoder_phys_vid_is_master(phys_enc))
		goto skip_flush;

	ctl->ops.get_bitmask_intf(ctl, &flush_mask, vid_enc->hw_intf->idx);
	ctl->ops.get_bitmask_intf(ctl, &flush_mask, phys_enc->hw_intf->idx);
	ctl->ops.update_pending_flush(ctl, flush_mask);

skip_flush:
	DPU_DEBUG_VIDENC(vid_enc, "update pending flush ctl %d flush_mask %x\n",
	DPU_DEBUG_VIDENC(phys_enc,
			 "update pending flush ctl %d flush_mask %x\n",
			 ctl->idx - CTL_0, flush_mask);

	/* ctl_flush & timing engine enable will be triggered by framework */
@@ -532,7 +523,7 @@ static void dpu_encoder_phys_vid_destroy(struct dpu_encoder_phys *phys_enc)
	}

	vid_enc = to_dpu_encoder_phys_vid(phys_enc);
	DPU_DEBUG_VIDENC(vid_enc, "\n");
	DPU_DEBUG_VIDENC(phys_enc, "\n");
	kfree(vid_enc);
}

@@ -589,7 +580,6 @@ static int dpu_encoder_phys_vid_wait_for_vblank(
static void dpu_encoder_phys_vid_prepare_for_kickoff(
		struct dpu_encoder_phys *phys_enc)
{
	struct dpu_encoder_phys_vid *vid_enc;
	struct dpu_hw_ctl *ctl;
	int rc;

@@ -597,7 +587,6 @@ static void dpu_encoder_phys_vid_prepare_for_kickoff(
		DPU_ERROR("invalid encoder/parameters\n");
		return;
	}
	vid_enc = to_dpu_encoder_phys_vid(phys_enc);

	ctl = phys_enc->hw_ctl;
	if (!ctl || !ctl->ops.wait_reset_status)
@@ -609,7 +598,7 @@ static void dpu_encoder_phys_vid_prepare_for_kickoff(
	 */
	rc = ctl->ops.wait_reset_status(ctl);
	if (rc) {
		DPU_ERROR_VIDENC(vid_enc, "ctl %d reset failure: %d\n",
		DPU_ERROR_VIDENC(phys_enc, "ctl %d reset failure: %d\n",
				ctl->idx, rc);
		dpu_encoder_helper_unregister_irq(phys_enc, INTR_IDX_VSYNC);
	}
@@ -618,7 +607,6 @@ static void dpu_encoder_phys_vid_prepare_for_kickoff(
static void dpu_encoder_phys_vid_disable(struct dpu_encoder_phys *phys_enc)
{
	struct msm_drm_private *priv;
	struct dpu_encoder_phys_vid *vid_enc;
	unsigned long lock_flags;
	int ret;

@@ -629,16 +617,13 @@ static void dpu_encoder_phys_vid_disable(struct dpu_encoder_phys *phys_enc)
	}
	priv = phys_enc->parent->dev->dev_private;

	vid_enc = to_dpu_encoder_phys_vid(phys_enc);
	if (!vid_enc->hw_intf || !phys_enc->hw_ctl) {
	if (!phys_enc->hw_intf || !phys_enc->hw_ctl) {
		DPU_ERROR("invalid hw_intf %d hw_ctl %d\n",
				vid_enc->hw_intf != 0, phys_enc->hw_ctl != 0);
				phys_enc->hw_intf != 0, phys_enc->hw_ctl != 0);
		return;
	}

	DPU_DEBUG_VIDENC(vid_enc, "\n");

	if (WARN_ON(!vid_enc->hw_intf->ops.enable_timing))
	if (WARN_ON(!phys_enc->hw_intf->ops.enable_timing))
		return;

	if (phys_enc->enable_state == DPU_ENC_DISABLED) {
@@ -647,7 +632,7 @@ static void dpu_encoder_phys_vid_disable(struct dpu_encoder_phys *phys_enc)
	}

	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
	vid_enc->hw_intf->ops.enable_timing(vid_enc->hw_intf, 0);
	phys_enc->hw_intf->ops.enable_timing(phys_enc->hw_intf, 0);
	if (dpu_encoder_phys_vid_is_master(phys_enc))
		dpu_encoder_phys_inc_pending(phys_enc);
	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
@@ -666,7 +651,7 @@ static void dpu_encoder_phys_vid_disable(struct dpu_encoder_phys *phys_enc)
			atomic_set(&phys_enc->pending_kickoff_cnt, 0);
			DRM_ERROR("wait disable failed: id:%u intf:%d ret:%d\n",
				  DRMID(phys_enc->parent),
				  vid_enc->hw_intf->idx - INTF_0, ret);
				  phys_enc->hw_intf->idx - INTF_0, ret);
		}
	}

@@ -677,25 +662,21 @@ static void dpu_encoder_phys_vid_handle_post_kickoff(
		struct dpu_encoder_phys *phys_enc)
{
	unsigned long lock_flags;
	struct dpu_encoder_phys_vid *vid_enc;

	if (!phys_enc) {
		DPU_ERROR("invalid encoder\n");
		return;
	}

	vid_enc = to_dpu_encoder_phys_vid(phys_enc);
	DPU_DEBUG_VIDENC(vid_enc, "enable_state %d\n", phys_enc->enable_state);

	/*
	 * Video mode must flush CTL before enabling timing engine
	 * Video encoders need to turn on their interfaces now
	 */
	if (phys_enc->enable_state == DPU_ENC_ENABLING) {
		trace_dpu_enc_phys_vid_post_kickoff(DRMID(phys_enc->parent),
				    vid_enc->hw_intf->idx - INTF_0);
				    phys_enc->hw_intf->idx - INTF_0);
		spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
		vid_enc->hw_intf->ops.enable_timing(vid_enc->hw_intf, 1);
		phys_enc->hw_intf->ops.enable_timing(phys_enc->hw_intf, 1);
		spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
		phys_enc->enable_state = DPU_ENC_ENABLED;
	}
@@ -704,16 +685,13 @@ static void dpu_encoder_phys_vid_handle_post_kickoff(
static void dpu_encoder_phys_vid_irq_control(struct dpu_encoder_phys *phys_enc,
		bool enable)
{
	struct dpu_encoder_phys_vid *vid_enc;
	int ret;

	if (!phys_enc)
		return;

	vid_enc = to_dpu_encoder_phys_vid(phys_enc);

	trace_dpu_enc_phys_vid_irq_ctrl(DRMID(phys_enc->parent),
			    vid_enc->hw_intf->idx - INTF_0,
			    phys_enc->hw_intf->idx - INTF_0,
			    enable,
			    atomic_read(&phys_enc->vblank_refcount));

@@ -732,19 +710,16 @@ static void dpu_encoder_phys_vid_irq_control(struct dpu_encoder_phys *phys_enc,
static int dpu_encoder_phys_vid_get_line_count(
		struct dpu_encoder_phys *phys_enc)
{
	struct dpu_encoder_phys_vid *vid_enc;

	if (!phys_enc)
		return -EINVAL;

	if (!dpu_encoder_phys_vid_is_master(phys_enc))
		return -EINVAL;

	vid_enc = to_dpu_encoder_phys_vid(phys_enc);
	if (!vid_enc->hw_intf || !vid_enc->hw_intf->ops.get_line_count)
	if (!phys_enc->hw_intf || !phys_enc->hw_intf->ops.get_line_count)
		return -EINVAL;

	return vid_enc->hw_intf->ops.get_line_count(vid_enc->hw_intf);
	return phys_enc->hw_intf->ops.get_line_count(phys_enc->hw_intf);
}

static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops)
@@ -791,7 +766,7 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
	phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
	phys_enc->intf_idx = p->intf_idx;

	DPU_DEBUG_VIDENC(vid_enc, "\n");
	DPU_DEBUG_VIDENC(phys_enc, "\n");

	dpu_encoder_phys_vid_init_ops(&phys_enc->ops);
	phys_enc->parent = p->parent;
@@ -825,7 +800,7 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
	phys_enc->enable_state = DPU_ENC_DISABLED;

	DPU_DEBUG_VIDENC(vid_enc, "created intf idx:%d\n", p->intf_idx);
	DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->intf_idx);

	return phys_enc;