drivers/gpu/drm/i915/display/skl_scaler.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/display/skl_scaler.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/display/skl_scaler.c
Extension
.c
Size
35620 bytes
Lines
1163
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 (*scaler_id >= 0) {
			scaler_state->scaler_users &= ~(1 << scaler_user);
			scaler_state->scalers[*scaler_id].in_use = false;

			drm_dbg_kms(display->drm,
				    "[CRTC:%d:%s] scaler_user index %u.%u: "
				    "Staged freeing scaler id %d scaler_users = 0x%x\n",
				    crtc->base.base.id, crtc->base.name,
				    crtc->pipe, scaler_user, *scaler_id,
				    scaler_state->scaler_users);
			*scaler_id = -1;
		}
		return 0;
	}

	skl_scaler_min_src_size(format, modifier, &min_src_w, &min_src_h);
	skl_scaler_max_src_size(display, &max_src_w, &max_src_h);

	skl_scaler_min_dst_size(&min_dst_w, &min_dst_h);
	skl_scaler_max_dst_size(crtc, &max_dst_w, &max_dst_h);

	/* range checks */
	if (src_w < min_src_w || src_h < min_src_h ||
	    dst_w < min_dst_w || dst_h < min_dst_h ||
	    src_w > max_src_w || src_h > max_src_h ||
	    dst_w > max_dst_w || dst_h > max_dst_h) {
		drm_dbg_kms(display->drm,
			    "[CRTC:%d:%s] scaler_user index %u.%u: src %ux%u dst %ux%u "
			    "size is out of scaler range\n",
			    crtc->base.base.id, crtc->base.name,
			    crtc->pipe, scaler_user, src_w, src_h,
			    dst_w, dst_h);
		return -EINVAL;
	}

	/*
	 * The pipe scaler does not use all the bits of PIPESRC, at least
	 * on the earlier platforms. So even when we're scaling a plane
	 * the *pipe* source size must not be too large. For simplicity
	 * we assume the limits match the scaler destination size limits.
	 * Might not be 100% accurate on all platforms, but good enough for
	 * now.
	 */
	if (pipe_src_w > max_dst_w || pipe_src_h > max_dst_h) {
		drm_dbg_kms(display->drm,
			    "[CRTC:%d:%s] scaler_user index %u.%u: pipe src size %ux%u "
			    "is out of scaler range\n",
			    crtc->base.base.id, crtc->base.name,
			    crtc->pipe, scaler_user, pipe_src_w, pipe_src_h);
		return -EINVAL;
	}

	/* mark this plane as a scaler user in crtc_state */
	scaler_state->scaler_users |= (1 << scaler_user);
	drm_dbg_kms(display->drm, "[CRTC:%d:%s] scaler_user index %u.%u: "
		    "staged scaling request for %ux%u->%ux%u scaler_users = 0x%x\n",
		    crtc->base.base.id, crtc->base.name,
		    crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h,
		    scaler_state->scaler_users);

	return 0;
}

int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
{
	const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
	int width, height;
	int ret;

	ret = intel_casf_compute_config(crtc_state);
	if (ret)
		return ret;

	if (crtc_state->pch_pfit.enabled) {
		width = drm_rect_width(&crtc_state->pch_pfit.dst);
		height = drm_rect_height(&crtc_state->pch_pfit.dst);
	} else {
		width = pipe_mode->crtc_hdisplay;
		height = pipe_mode->crtc_vdisplay;
	}
	return skl_update_scaler(crtc_state, !crtc_state->hw.active,
				 SKL_CRTC_INDEX,
				 &crtc_state->scaler_state.scaler_id,
				 drm_rect_width(&crtc_state->pipe_src),
				 drm_rect_height(&crtc_state->pipe_src),
				 width, height, NULL, 0,
				 crtc_state->pch_pfit.enabled);
}

/**

Annotation

Implementation Notes