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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
Extension
.c
Size
54532 bytes
Lines
1942
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 (rc) {
			if (rc != -ENODATA)
				DRM_DEBUG_DRIVER("MISR read failed\n");
			return rc;
		}
	}

	return drm_crtc_add_crc_entry(crtc, true,
			drm_crtc_accurate_vblank_count(crtc), crcs);
}

static int dpu_crtc_get_encoder_crc(struct drm_crtc *crtc)
{
	struct drm_encoder *drm_enc;
	int rc, pos = 0;
	u32 crcs[INTF_MAX];

	drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask) {
		rc = dpu_encoder_get_crc(drm_enc, crcs, pos);
		if (rc < 0) {
			if (rc != -ENODATA)
				DRM_DEBUG_DRIVER("MISR read failed\n");

			return rc;
		}

		pos += rc;
	}

	return drm_crtc_add_crc_entry(crtc, true,
			drm_crtc_accurate_vblank_count(crtc), crcs);
}

static int dpu_crtc_get_crc(struct drm_crtc *crtc)
{
	struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state);

	/* Skip first 2 frames in case of "uncooked" CRCs */
	if (crtc_state->crc_frame_skip_count < 2) {
		crtc_state->crc_frame_skip_count++;
		return 0;
	}

	if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
		return dpu_crtc_get_lm_crc(crtc, crtc_state);
	else if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_ENCODER)
		return dpu_crtc_get_encoder_crc(crtc);

	return -EINVAL;
}

static bool dpu_crtc_get_scanout_position(struct drm_crtc *crtc,
					   bool in_vblank_irq,
					   int *vpos, int *hpos,
					   ktime_t *stime, ktime_t *etime,
					   const struct drm_display_mode *mode)
{
	unsigned int pipe = crtc->index;
	struct drm_encoder *encoder;
	int line, vsw, vbp, vactive_start, vactive_end, vfp_end;

	encoder = get_encoder_from_crtc(crtc);
	if (!encoder) {
		DRM_ERROR("no encoder found for crtc %d\n", pipe);
		return false;
	}

	vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
	vbp = mode->crtc_vtotal - mode->crtc_vsync_end;

	/*
	 * the line counter is 1 at the start of the VSYNC pulse and VTOTAL at
	 * the end of VFP. Translate the porch values relative to the line
	 * counter positions.
	 */

	vactive_start = vsw + vbp + 1;
	vactive_end = vactive_start + mode->crtc_vdisplay;

	/* last scan line before VSYNC */
	vfp_end = mode->crtc_vtotal;

	if (stime)
		*stime = ktime_get();

	line = dpu_encoder_get_linecount(encoder);

	if (line < vactive_start)
		line -= vactive_start;
	else if (line > vactive_end)

Annotation

Implementation Notes