drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
Extension
.c
Size
24777 bytes
Lines
792
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ret) {
			atomic_set(&phys_enc->pending_kickoff_cnt, 0);
			DRM_ERROR("wait disable failed: id:%u intf:%d ret:%d\n",
				  DRMID(phys_enc->parent),
				  phys_enc->hw_intf->idx - INTF_0, ret);
		}
	}

	if (phys_enc->hw_intf && phys_enc->hw_intf->ops.get_status)
		phys_enc->hw_intf->ops.get_status(phys_enc->hw_intf, &intf_status);

	/*
	 * Wait for a vsync if timing en status is on after timing engine
	 * is disabled.
	 */
	if (intf_status.is_en && dpu_encoder_phys_vid_is_master(phys_enc)) {
		spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
		dpu_encoder_phys_inc_pending(phys_enc);
		spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
		ret = dpu_encoder_phys_vid_wait_for_tx_complete(phys_enc);
		if (ret) {
			atomic_set(&phys_enc->pending_kickoff_cnt, 0);
			DRM_ERROR("wait disable failed: id:%u intf:%d ret:%d\n",
				  DRMID(phys_enc->parent),
				  phys_enc->hw_intf->idx - INTF_0, ret);
		}
	}

	dpu_encoder_helper_phys_cleanup(phys_enc);
	phys_enc->enable_state = DPU_ENC_DISABLED;
}

static void dpu_encoder_phys_vid_handle_post_kickoff(
		struct dpu_encoder_phys *phys_enc)
{
	unsigned long lock_flags;

	/*
	 * 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),
				    phys_enc->hw_intf->idx - INTF_0);
		spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
		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;
	}
}

static void dpu_encoder_phys_vid_irq_enable(struct dpu_encoder_phys *phys_enc)
{
	int ret;

	trace_dpu_enc_phys_vid_irq_enable(DRMID(phys_enc->parent),
					  phys_enc->hw_intf->idx - INTF_0,
					  phys_enc->vblank_refcount);

	ret = dpu_encoder_phys_vid_control_vblank_irq(phys_enc, true);
	if (WARN_ON(ret))
		return;

	dpu_core_irq_register_callback(phys_enc->dpu_kms,
				       phys_enc->irq[INTR_IDX_UNDERRUN],
				       dpu_encoder_phys_vid_underrun_irq,
				       phys_enc);
}

static void dpu_encoder_phys_vid_irq_disable(struct dpu_encoder_phys *phys_enc)
{
	trace_dpu_enc_phys_vid_irq_disable(DRMID(phys_enc->parent),
					   phys_enc->hw_intf->idx - INTF_0,
					   phys_enc->vblank_refcount);

	dpu_encoder_phys_vid_control_vblank_irq(phys_enc, false);
	dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
					 phys_enc->irq[INTR_IDX_UNDERRUN]);
}

static int dpu_encoder_phys_vid_get_line_count(
		struct dpu_encoder_phys *phys_enc)
{
	if (!dpu_encoder_phys_vid_is_master(phys_enc))
		return -EINVAL;

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

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

Annotation

Implementation Notes