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

Commit 05ef8238 authored by Lloyd Atkinson's avatar Lloyd Atkinson
Browse files

drm/msm/sde: refactor encoder irq code into common helpers



Reduce code duplication by refactoring common irq registration
and waiting functionality into utility functions in the sde
encoder that physical encoders can leverage.

Change-Id: I361d6e84238ae51161b57821ea4bf48a45c36942
Signed-off-by: default avatarLloyd Atkinson <latkinso@codeaurora.org>
parent ffd90498
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -195,6 +195,12 @@ u32 sde_core_irq_read(struct sde_kms *sde_kms, int irq_idx, bool clear)
			!sde_kms->hw_intr->ops.get_interrupt_status)
		return 0;

	if (irq_idx < 0) {
		SDE_ERROR("[%pS] invalid irq_idx=%d\n",
				__builtin_return_address(0), irq_idx);
		return 0;
	}

	return sde_kms->hw_intr->ops.get_interrupt_status(sde_kms->hw_intr,
			irq_idx, clear);
}
+189 −8
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include "sde_hw_dsc.h"
#include "sde_crtc.h"
#include "sde_trace.h"
#include "sde_core_irq.h"

#define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\
		(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
@@ -43,6 +44,18 @@
#define SDE_ERROR_ENC(e, fmt, ...) SDE_ERROR("enc%d " fmt,\
		(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)

#define SDE_DEBUG_PHYS(p, fmt, ...) SDE_DEBUG("enc%d intf%d pp%d " fmt,\
		(p) ? (p)->parent->base.id : -1, \
		(p) ? (p)->intf_idx - INTF_0 : -1, \
		(p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
		##__VA_ARGS__)

#define SDE_ERROR_PHYS(p, fmt, ...) SDE_ERROR("enc%d intf%d pp%d " fmt,\
		(p) ? (p)->parent->base.id : -1, \
		(p) ? (p)->intf_idx - INTF_0 : -1, \
		(p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
		##__VA_ARGS__)

/* timeout in frames waiting for frame done */
#define SDE_ENCODER_FRAME_DONE_TIMEOUT	60

@@ -278,6 +291,174 @@ static inline int _sde_encoder_power_enable(struct sde_encoder_virt *sde_enc,
									enable);
}

void sde_encoder_helper_report_irq_timeout(struct sde_encoder_phys *phys_enc,
		enum sde_intr_idx intr_idx)
{
	SDE_EVT32(DRMID(phys_enc->parent),
			phys_enc->intf_idx - INTF_0,
			phys_enc->hw_pp->idx - PINGPONG_0,
			intr_idx);
	SDE_ERROR_PHYS(phys_enc, "irq %d timeout\n", intr_idx);

	if (phys_enc->parent_ops.handle_frame_done)
		phys_enc->parent_ops.handle_frame_done(
				phys_enc->parent, phys_enc,
				SDE_ENCODER_FRAME_EVENT_ERROR);
}

int sde_encoder_helper_wait_for_irq(struct sde_encoder_phys *phys_enc,
		enum sde_intr_idx intr_idx,
		struct sde_encoder_wait_info *wait_info)
{
	struct sde_encoder_irq *irq;
	u32 irq_status;
	int ret;

	if (!phys_enc || !wait_info || intr_idx >= INTR_IDX_MAX) {
		SDE_ERROR("invalid params\n");
		return -EINVAL;
	}
	irq = &phys_enc->irq[intr_idx];

	/* note: do master / slave checking outside */

	/* return EWOULDBLOCK since we know the wait isn't necessary */
	if (phys_enc->enable_state == SDE_ENC_DISABLED) {
		SDE_ERROR_PHYS(phys_enc, "encoder is disabled\n");
		return -EWOULDBLOCK;
	}

	if (irq->irq_idx < 0) {
		SDE_DEBUG_PHYS(phys_enc, "irq %s hw %d disabled, skip wait\n",
				irq->name, irq->hw_idx);
		SDE_EVT32(DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
				irq->irq_idx);
		return 0;
	}

	SDE_DEBUG_PHYS(phys_enc, "pending_cnt %d\n",
			atomic_read(wait_info->atomic_cnt));
	SDE_EVT32(DRMID(phys_enc->parent), irq->hw_idx,
			atomic_read(wait_info->atomic_cnt),
			SDE_EVTLOG_FUNC_ENTRY);

	ret = sde_encoder_helper_wait_event_timeout(
			DRMID(phys_enc->parent),
			irq->hw_idx,
			wait_info);

	if (ret <= 0) {
		irq_status = sde_core_irq_read(phys_enc->sde_kms,
				irq->irq_idx, true);
		if (irq_status) {
			unsigned long flags;

			SDE_EVT32(DRMID(phys_enc->parent),
					irq->hw_idx,
					atomic_read(wait_info->atomic_cnt));
			SDE_DEBUG_PHYS(phys_enc,
					"done but irq %d not triggered\n",
					irq->irq_idx);
			local_irq_save(flags);
			irq->cb.func(phys_enc, irq->irq_idx);
			local_irq_restore(flags);
			ret = 0;
		} else {
			ret = -ETIMEDOUT;
		}
	} else {
		ret = 0;
	}

	SDE_EVT32(DRMID(phys_enc->parent), irq->hw_idx, ret,
			SDE_EVTLOG_FUNC_EXIT);

	return ret;
}

int sde_encoder_helper_register_irq(struct sde_encoder_phys *phys_enc,
		enum sde_intr_idx intr_idx)
{
	struct sde_encoder_irq *irq;
	int ret = 0;

	if (!phys_enc || intr_idx >= INTR_IDX_MAX) {
		SDE_ERROR("invalid params\n");
		return -EINVAL;
	}
	irq = &phys_enc->irq[intr_idx];

	if (irq->irq_idx >= 0) {
		SDE_ERROR_PHYS(phys_enc,
				"skipping already registered irq %s type %d\n",
				irq->name, irq->intr_type);
		return 0;
	}

	irq->irq_idx = sde_core_irq_idx_lookup(phys_enc->sde_kms,
			irq->intr_type, irq->hw_idx);
	if (irq->irq_idx < 0) {
		SDE_ERROR_PHYS(phys_enc,
			"failed to lookup IRQ index for %s type:%d\n",
			irq->name, irq->intr_type);
		return -EINVAL;
	}

	ret = sde_core_irq_register_callback(phys_enc->sde_kms, irq->irq_idx,
			&irq->cb);
	if (ret) {
		SDE_ERROR_PHYS(phys_enc,
			"failed to register IRQ callback for %s\n",
			irq->name);
		irq->irq_idx = -EINVAL;
		return ret;
	}

	ret = sde_core_irq_enable(phys_enc->sde_kms, &irq->irq_idx, 1);
	if (ret) {
		SDE_ERROR_PHYS(phys_enc,
			"enable IRQ for intr:%s failed, irq_idx %d\n",
			irq->name, irq->irq_idx);

		sde_core_irq_unregister_callback(phys_enc->sde_kms,
				irq->irq_idx, &irq->cb);
		irq->irq_idx = -EINVAL;
		return ret;
	}

	SDE_EVT32(DRMID(phys_enc->parent), intr_idx, irq->hw_idx, irq->irq_idx);
	SDE_DEBUG_PHYS(phys_enc, "registered irq %s idx: %d\n",
			irq->name, irq->irq_idx);

	return ret;
}

int sde_encoder_helper_unregister_irq(struct sde_encoder_phys *phys_enc,
		enum sde_intr_idx intr_idx)
{
	struct sde_encoder_irq *irq;

	if (!phys_enc) {
		SDE_ERROR("invalid encoder\n");
		return -EINVAL;
	}
	irq = &phys_enc->irq[intr_idx];

	/* silently skip irqs that weren't registered */
	if (irq->irq_idx < 0)
		return 0;

	sde_core_irq_disable(phys_enc->sde_kms, &irq->irq_idx, 1);
	sde_core_irq_unregister_callback(phys_enc->sde_kms, irq->irq_idx,
			&irq->cb);
	irq->irq_idx = -EINVAL;

	SDE_EVT32(DRMID(phys_enc->parent), intr_idx, irq->hw_idx, irq->irq_idx);
	SDE_DEBUG_PHYS(phys_enc, "unregistered %d\n", irq->irq_idx);

	return 0;
}

void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc,
		struct sde_encoder_hw_resources *hw_res,
		struct drm_connector_state *conn_state)
@@ -1787,23 +1968,23 @@ void sde_encoder_helper_trigger_start(struct sde_encoder_phys *phys_enc)
int sde_encoder_helper_wait_event_timeout(
		int32_t drm_id,
		int32_t hw_id,
		wait_queue_head_t *wq,
		atomic_t *cnt,
		s64 timeout_ms)
		struct sde_encoder_wait_info *info)
{
	int rc = 0;
	s64 expected_time = ktime_to_ms(ktime_get()) + timeout_ms;
	s64 jiffies = msecs_to_jiffies(timeout_ms);
	s64 expected_time = ktime_to_ms(ktime_get()) + info->timeout_ms;
	s64 jiffies = msecs_to_jiffies(info->timeout_ms);
	s64 time;

	do {
		rc = wait_event_timeout(*wq, atomic_read(cnt) == 0, jiffies);
		rc = wait_event_timeout(*(info->wq),
				atomic_read(info->atomic_cnt) == 0, jiffies);
		time = ktime_to_ms(ktime_get());

		SDE_EVT32(drm_id, hw_id, rc, time, expected_time,
				atomic_read(cnt));
				atomic_read(info->atomic_cnt));
	/* If we timed out, counter is valid and time is less, wait again */
	} while (atomic_read(cnt) && (rc == 0) && (time < expected_time));
	} while (atomic_read(info->atomic_cnt) && (rc == 0) &&
			(time < expected_time));

	return rc;
}
+74 −16
Original line number Diff line number Diff line
@@ -179,6 +179,25 @@ enum sde_intr_idx {
	INTR_IDX_MAX,
};

/**
 * sde_encoder_irq - tracking structure for interrupts
 * @name:		string name of interrupt
 * @intr_type:		Encoder interrupt type
 * @intr_idx:		Encoder interrupt enumeration
 * @hw_idx:		HW Block ID
 * @irq_idx:		IRQ interface lookup index from SDE IRQ framework
 *			will be -EINVAL if IRQ is not registered
 * @irq_cb:		interrupt callback
 */
struct sde_encoder_irq {
	const char *name;
	enum sde_intr_type intr_type;
	enum sde_intr_idx intr_idx;
	int hw_idx;
	int irq_idx;
	struct sde_irq_callback cb;
};

/**
 * struct sde_encoder_phys - physical encoder that drives a single INTF block
 *	tied to a specific panel / sub-panel. Abstract type, sub-classed by
@@ -211,6 +230,7 @@ enum sde_intr_idx {
 * @pending_ctlstart_cnt:	Atomic counter tracking the number of ctl start
 *                              pending.
 * @pending_kickoff_wq:		Wait queue for blocking until kickoff completes
 * @irq:			IRQ tracking structures
 */
struct sde_encoder_phys {
	struct drm_encoder *parent;
@@ -236,6 +256,7 @@ struct sde_encoder_phys {
	atomic_t pending_ctlstart_cnt;
	atomic_t pending_kickoff_cnt;
	wait_queue_head_t pending_kickoff_wq;
	struct sde_encoder_irq irq[INTR_IDX_MAX];
};

static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys)
@@ -248,16 +269,12 @@ static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys)
 * struct sde_encoder_phys_vid - sub-class of sde_encoder_phys to handle video
 *	mode specific operations
 * @base:	Baseclass physical encoder structure
 * @irq_idx:	IRQ interface lookup index
 * @irq_cb:	interrupt callback
 * @hw_intf:	Hardware interface to the intf registers
 * @timing_params: Current timing parameter
 * @rot_prefill_line: number of line to prefill for inline rotation; 0 disable
 */
struct sde_encoder_phys_vid {
	struct sde_encoder_phys base;
	int irq_idx[INTR_IDX_MAX];
	struct sde_irq_callback irq_cb[INTR_IDX_MAX];
	struct sde_hw_intf *hw_intf;
	struct intf_timing_params timing_params;
	u64 rot_prefill_line;
@@ -269,10 +286,6 @@ struct sde_encoder_phys_vid {
 * @base:	Baseclass physical encoder structure
 * @intf_idx:	Intf Block index used by this phys encoder
 * @stream_sel:	Stream selection for multi-stream interfaces
 * @pp_rd_ptr_irq_idx:	IRQ signifying panel's frame read pointer
 *			For CMD encoders, VBLANK is driven by the PP RD Done IRQ
 * @pp_tx_done_irq_idx:	IRQ signifying frame transmission to panel complete
 * @irq_cb:		interrupt callback
 * @serialize_wait4pp:	serialize wait4pp feature waits for pp_done interrupt
 *			after ctl_start instead of before next frame kickoff
 * @pp_timeout_report_cnt: number of pingpong done irq timeout errors
@@ -280,8 +293,6 @@ struct sde_encoder_phys_vid {
struct sde_encoder_phys_cmd {
	struct sde_encoder_phys base;
	int stream_sel;
	int irq_idx[INTR_IDX_MAX];
	struct sde_irq_callback irq_cb[INTR_IDX_MAX];
	bool serialize_wait4pp;
	int pp_timeout_report_cnt;
};
@@ -354,6 +365,18 @@ struct sde_enc_phys_init_params {
	spinlock_t *enc_spinlock;
};

/**
 * sde_encoder_wait_info - container for passing arguments to irq wait functions
 * @wq: wait queue structure
 * @atomic_cnt: wait until atomic_cnt equals zero
 * @timeout_ms: timeout value in milliseconds
 */
struct sde_encoder_wait_info {
	wait_queue_head_t *wq;
	atomic_t *atomic_cnt;
	s64 timeout_ms;
};

/**
 * sde_encoder_phys_vid_init - Construct a new video mode physical encoder
 * @p:	Pointer to init params structure
@@ -406,16 +429,12 @@ void sde_encoder_helper_trigger_start(struct sde_encoder_phys *phys_enc);
 *	making sure that elapsed time during wait is valid.
 * @drm_id: drm object id for logging
 * @hw_id: hw instance id for logging
 * @wq: wait queue structure
 * @cnt: atomic counter to wait on
 * @timeout_ms: timeout value in milliseconds
 * @info: wait info structure
 */
int sde_encoder_helper_wait_event_timeout(
		int32_t drm_id,
		int32_t hw_id,
		wait_queue_head_t *wq,
		atomic_t *cnt,
		s64 timeout_ms);
		struct sde_encoder_wait_info *info);

/**
 * sde_encoder_helper_hw_reset - issue ctl hw reset
@@ -463,4 +482,43 @@ void sde_encoder_helper_split_config(
int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc,
		struct drm_framebuffer *fb);

/**
 * sde_encoder_helper_report_irq_timeout - utility to report error that irq has
 *	timed out, including reporting frame error event to crtc and debug dump
 * @phys_enc: Pointer to physical encoder structure
 * @intr_idx: Failing interrupt index
 */
void sde_encoder_helper_report_irq_timeout(struct sde_encoder_phys *phys_enc,
		enum sde_intr_idx intr_idx);

/**
 * sde_encoder_helper_wait_for_irq - utility to wait on an irq.
 *	note: will call sde_encoder_helper_wait_for_irq on timeout
 * @phys_enc: Pointer to physical encoder structure
 * @intr_idx: encoder interrupt index
 * @wait_info: wait info struct
 * @Return: 0 or -ERROR
 */
int sde_encoder_helper_wait_for_irq(struct sde_encoder_phys *phys_enc,
		enum sde_intr_idx intr_idx,
		struct sde_encoder_wait_info *wait_info);

/**
 * sde_encoder_helper_register_irq - register and enable an irq
 * @phys_enc: Pointer to physical encoder structure
 * @intr_idx: encoder interrupt index
 * @Return: 0 or -ERROR
 */
int sde_encoder_helper_register_irq(struct sde_encoder_phys *phys_enc,
		enum sde_intr_idx intr_idx);

/**
 * sde_encoder_helper_unregister_irq - unregister and disable an irq
 * @phys_enc: Pointer to physical encoder structure
 * @intr_idx: encoder interrupt index
 * @Return: 0 or -ERROR
 */
int sde_encoder_helper_unregister_irq(struct sde_encoder_phys *phys_enc,
		enum sde_intr_idx intr_idx);

#endif /* __sde_encoder_phys_H__ */
+155 −258

File changed.

Preview size limit exceeded, changes collapsed.

+59 −137
Original line number Diff line number Diff line
@@ -345,17 +345,17 @@ static void sde_encoder_phys_vid_setup_timing_engine(

static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
{
	struct sde_encoder_phys_vid *vid_enc = arg;
	struct sde_encoder_phys *phys_enc;
	struct sde_encoder_phys *phys_enc = arg;
	struct sde_encoder_phys_vid *vid_enc =
			to_sde_encoder_phys_vid(phys_enc);
	struct sde_hw_ctl *hw_ctl;
	unsigned long lock_flags;
	u32 flush_register = 0;
	int new_cnt = -1, old_cnt = -1;

	if (!vid_enc)
	if (!phys_enc)
		return;

	phys_enc = &vid_enc->base;
	hw_ctl = phys_enc->hw_ctl;

	if (phys_enc->parent_ops.handle_vblank_virt)
@@ -387,13 +387,11 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)

static void sde_encoder_phys_vid_underrun_irq(void *arg, int irq_idx)
{
	struct sde_encoder_phys_vid *vid_enc = arg;
	struct sde_encoder_phys *phys_enc;
	struct sde_encoder_phys *phys_enc = arg;

	if (!vid_enc)
	if (!phys_enc)
		return;

	phys_enc = &vid_enc->base;
	if (phys_enc->parent_ops.handle_underrun_virt)
		phys_enc->parent_ops.handle_underrun_virt(phys_enc->parent,
			phys_enc);
@@ -419,77 +417,18 @@ static bool sde_encoder_phys_vid_needs_single_flush(
	return phys_enc && _sde_encoder_phys_is_ppsplit(phys_enc);
}

static int sde_encoder_phys_vid_register_irq(struct sde_encoder_phys *phys_enc,
	enum sde_intr_type intr_type, int idx,
	void (*irq_func)(void *, int), const char *irq_name)
{
	struct sde_encoder_phys_vid *vid_enc;
	int ret = 0;

	if (!phys_enc) {
		SDE_ERROR("invalid encoder\n");
		return -EINVAL;
	}

	vid_enc = to_sde_encoder_phys_vid(phys_enc);
	vid_enc->irq_idx[idx] = sde_core_irq_idx_lookup(phys_enc->sde_kms,
			intr_type, vid_enc->hw_intf->idx);
	if (vid_enc->irq_idx[idx] < 0) {
		SDE_ERROR_VIDENC(vid_enc,
			"failed to lookup IRQ index for %s type:%d\n", irq_name,
			intr_type);
		return -EINVAL;
	}

	vid_enc->irq_cb[idx].func = irq_func;
	vid_enc->irq_cb[idx].arg = vid_enc;
	ret = sde_core_irq_register_callback(phys_enc->sde_kms,
			vid_enc->irq_idx[idx], &vid_enc->irq_cb[idx]);
	if (ret) {
		SDE_ERROR_VIDENC(vid_enc,
			"failed to register IRQ callback for %s\n", irq_name);
		return ret;
	}

	ret = sde_core_irq_enable(phys_enc->sde_kms, &vid_enc->irq_idx[idx], 1);
	if (ret) {
		SDE_ERROR_VIDENC(vid_enc,
			"enable IRQ for intr:%s failed, irq_idx %d\n",
			irq_name, vid_enc->irq_idx[idx]);
		vid_enc->irq_idx[idx] = -EINVAL;

		/* unregister callback on IRQ enable failure */
		sde_core_irq_unregister_callback(phys_enc->sde_kms,
				vid_enc->irq_idx[idx], &vid_enc->irq_cb[idx]);
		return ret;
	}

	SDE_DEBUG_VIDENC(vid_enc, "registered irq %s idx: %d\n",
			irq_name, vid_enc->irq_idx[idx]);

	return ret;
}

static int sde_encoder_phys_vid_unregister_irq(
	struct sde_encoder_phys *phys_enc, int idx)
static void _sde_encoder_phys_vid_setup_irq_hw_idx(
		struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_phys_vid *vid_enc;

	if (!phys_enc) {
		SDE_ERROR("invalid encoder\n");
		goto end;
	}

	vid_enc = to_sde_encoder_phys_vid(phys_enc);
	sde_core_irq_disable(phys_enc->sde_kms, &vid_enc->irq_idx[idx], 1);

	sde_core_irq_unregister_callback(phys_enc->sde_kms,
			vid_enc->irq_idx[idx], &vid_enc->irq_cb[idx]);
	struct sde_encoder_irq *irq;

	SDE_DEBUG_VIDENC(vid_enc, "unregistered %d\n", vid_enc->irq_idx[idx]);
	irq = &phys_enc->irq[INTR_IDX_VSYNC];
	irq->hw_idx = phys_enc->intf_idx;
	irq->irq_idx = -EINVAL;

end:
	return 0;
	irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
	irq->hw_idx = phys_enc->intf_idx;
	irq->irq_idx = -EINVAL;
}

static void sde_encoder_phys_vid_mode_set(
@@ -527,6 +466,8 @@ static void sde_encoder_phys_vid_mode_set(
		phys_enc->hw_ctl = NULL;
		return;
	}

	_sde_encoder_phys_vid_setup_irq_hw_idx(phys_enc);
}

static int sde_encoder_phys_vid_control_vblank_irq(
@@ -555,12 +496,9 @@ static int sde_encoder_phys_vid_control_vblank_irq(
			atomic_read(&phys_enc->vblank_refcount));

	if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
		ret = sde_encoder_phys_vid_register_irq(phys_enc,
			SDE_IRQ_TYPE_INTF_VSYNC,
			INTR_IDX_VSYNC,
			sde_encoder_phys_vid_vblank_irq, "vsync_irq");
		ret = sde_encoder_helper_register_irq(phys_enc, INTR_IDX_VSYNC);
	else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
		ret = sde_encoder_phys_vid_unregister_irq(phys_enc,
		ret = sde_encoder_helper_unregister_irq(phys_enc,
				INTR_IDX_VSYNC);

	if (ret)
@@ -608,10 +546,7 @@ static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc)
	if (ret)
		goto end;

	ret = sde_encoder_phys_vid_register_irq(phys_enc,
		SDE_IRQ_TYPE_INTF_UNDER_RUN,
		INTR_IDX_UNDERRUN,
		sde_encoder_phys_vid_underrun_irq, "underrun");
	ret = sde_encoder_helper_register_irq(phys_enc, INTR_IDX_UNDERRUN);
	if (ret) {
		sde_encoder_phys_vid_control_vblank_irq(phys_enc, false);
		goto end;
@@ -680,9 +615,11 @@ static void sde_encoder_phys_vid_get_hw_resources(
static int sde_encoder_phys_vid_wait_for_vblank(
		struct sde_encoder_phys *phys_enc, bool notify)
{
	struct sde_encoder_phys_vid *vid_enc =
			to_sde_encoder_phys_vid(phys_enc);
	u32 irq_status;
	struct sde_encoder_wait_info wait_info = {
		.wq = &phys_enc->pending_kickoff_wq,
		.atomic_cnt = &phys_enc->pending_kickoff_cnt,
		.timeout_ms = KICKOFF_TIMEOUT_MS,
	};
	int ret;

	if (!sde_encoder_phys_vid_is_master(phys_enc)) {
@@ -695,54 +632,18 @@ static int sde_encoder_phys_vid_wait_for_vblank(
		return 0;
	}

	if (phys_enc->enable_state != SDE_ENC_ENABLED) {
		SDE_ERROR("encoder not enabled\n");
		return -EWOULDBLOCK;
	}

	SDE_EVT32(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0,
			SDE_EVTLOG_FUNC_ENTRY);

	/* Wait for kickoff to complete */
	ret = sde_encoder_helper_wait_event_timeout(
			DRMID(phys_enc->parent),
			vid_enc->hw_intf->idx - INTF_0,
			&phys_enc->pending_kickoff_wq,
			&phys_enc->pending_kickoff_cnt,
			KICKOFF_TIMEOUT_MS);
	if (ret <= 0) {
		irq_status = sde_core_irq_read(phys_enc->sde_kms,
				vid_enc->irq_idx[INTR_IDX_VSYNC], true);
		if (irq_status) {
			SDE_EVT32(DRMID(phys_enc->parent),
					vid_enc->hw_intf->idx - INTF_0);
			SDE_DEBUG_VIDENC(vid_enc, "done, irq not triggered\n");
			if (notify && phys_enc->parent_ops.handle_frame_done)
				phys_enc->parent_ops.handle_frame_done(
						phys_enc->parent, phys_enc,
						SDE_ENCODER_FRAME_EVENT_DONE);
			sde_encoder_phys_vid_vblank_irq(vid_enc,
					INTR_IDX_VSYNC);
			ret = 0;
		} else {
			SDE_EVT32(DRMID(phys_enc->parent),
					vid_enc->hw_intf->idx - INTF_0);
			SDE_ERROR_VIDENC(vid_enc, "kickoff timed out\n");
			if (notify && phys_enc->parent_ops.handle_frame_done)
				phys_enc->parent_ops.handle_frame_done(
						phys_enc->parent, phys_enc,
						SDE_ENCODER_FRAME_EVENT_ERROR);
			ret = -ETIMEDOUT;
		}
	} else {
		if (notify && phys_enc->parent_ops.handle_frame_done)
	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC,
			&wait_info);

	if (ret == -ETIMEDOUT) {
		sde_encoder_helper_report_irq_timeout(phys_enc, INTR_IDX_VSYNC);
	} else if (!ret && notify && phys_enc->parent_ops.handle_frame_done)
		phys_enc->parent_ops.handle_frame_done(
				phys_enc->parent, phys_enc,
				SDE_ENCODER_FRAME_EVENT_DONE);
		ret = 0;
	}

	return 0;
	return ret;
}

static int sde_encoder_phys_vid_wait_for_commit_done(
@@ -845,6 +746,8 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
		sde_encoder_phys_vid_control_vblank_irq(phys_enc, false);
	}

	sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_UNDERRUN);

	if (atomic_read(&phys_enc->vblank_refcount))
		SDE_ERROR_VIDENC(vid_enc, "invalid vblank refcount %d\n",
				atomic_read(&phys_enc->vblank_refcount));
@@ -932,6 +835,7 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
	struct sde_encoder_phys_vid *vid_enc = NULL;
	struct sde_rm_hw_iter iter;
	struct sde_hw_mdp *hw_mdp;
	struct sde_encoder_irq *irq;
	int i, ret = 0;

	if (!p) {
@@ -986,8 +890,26 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
	phys_enc->intf_mode = INTF_MODE_VIDEO;
	phys_enc->enc_spinlock = p->enc_spinlock;
	phys_enc->comp_type = p->comp_type;
	for (i = 0; i < INTR_IDX_MAX; i++)
		INIT_LIST_HEAD(&vid_enc->irq_cb[i].list);
	for (i = 0; i < INTR_IDX_MAX; i++) {
		irq = &phys_enc->irq[i];
		INIT_LIST_HEAD(&irq->cb.list);
		irq->irq_idx = -EINVAL;
		irq->hw_idx = -EINVAL;
		irq->cb.arg = phys_enc;
	}

	irq = &phys_enc->irq[INTR_IDX_VSYNC];
	irq->name = "vsync_irq";
	irq->intr_type = SDE_IRQ_TYPE_INTF_VSYNC;
	irq->intr_idx = INTR_IDX_VSYNC;
	irq->cb.func = sde_encoder_phys_vid_vblank_irq;

	irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
	irq->name = "underrun";
	irq->intr_type = SDE_IRQ_TYPE_INTF_UNDER_RUN;
	irq->intr_idx = INTR_IDX_UNDERRUN;
	irq->cb.func = sde_encoder_phys_vid_underrun_irq;

	atomic_set(&phys_enc->vblank_refcount, 0);
	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
Loading