Loading drivers/gpu/drm/msm/sde/sde_core_irq.c +6 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading drivers/gpu/drm/msm/sde/sde_encoder.c +189 −8 Original line number Diff line number Diff line Loading @@ -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__) Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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; } Loading drivers/gpu/drm/msm/sde/sde_encoder_phys.h +74 −16 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading @@ -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) Loading @@ -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; Loading @@ -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 Loading @@ -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; }; Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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__ */ drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +155 −258 File changed.Preview size limit exceeded, changes collapsed. Show changes drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +59 −137 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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); Loading @@ -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( Loading Loading @@ -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( Loading Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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)) { Loading @@ -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( Loading Loading @@ -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)); Loading Loading @@ -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) { Loading Loading @@ -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 Loading
drivers/gpu/drm/msm/sde/sde_core_irq.c +6 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +189 −8 Original line number Diff line number Diff line Loading @@ -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__) Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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; } Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys.h +74 −16 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading @@ -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) Loading @@ -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; Loading @@ -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 Loading @@ -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; }; Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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__ */
drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +155 −258 File changed.Preview size limit exceeded, changes collapsed. Show changes
drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +59 −137 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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); Loading @@ -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( Loading Loading @@ -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( Loading Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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)) { Loading @@ -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( Loading Loading @@ -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)); Loading Loading @@ -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) { Loading Loading @@ -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