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

Commit 11ce4393 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/sde: refactor encoder irq code into common helpers"

parents 4397a218 05ef8238
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
@@ -182,6 +182,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
@@ -214,6 +233,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;
@@ -239,6 +259,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)
@@ -251,16 +272,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;
@@ -272,10 +289,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
@@ -283,8 +296,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;
};
@@ -357,6 +368,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
@@ -409,16 +432,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
@@ -466,4 +485,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