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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/display/intel_cursor.c
Extension
.c
Size
32749 bytes
Lines
1116
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

drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
		drm_dbg_kms(display->drm,
			    "[PLANE:%d:%s] invalid cursor stride (%u) (cursor width %d)\n",
			    plane->base.base.id, plane->base.name,
			    fb->pitches[0], drm_rect_width(&plane_state->uapi.dst));
		return -EINVAL;
	}

	/*
	 * There's something wrong with the cursor on CHV pipe C.
	 * If it straddles the left edge of the screen then
	 * moving it away from the edge or disabling it often
	 * results in a pipe underrun, and often that can lead to
	 * dead pipe (constant underrun reported, and it scans
	 * out just a solid color). To recover from that, the
	 * display power well must be turned off and on again.
	 * Refuse the put the cursor into that compromised position.
	 */
	if (display->platform.cherryview && pipe == PIPE_C &&
	    plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
		drm_dbg_kms(display->drm,
			    "[PLANE:%d:%s] cursor not allowed to straddle the left screen edge\n",
			    plane->base.base.id, plane->base.name);
		return -EINVAL;
	}

	plane_state->ctl = i9xx_cursor_ctl(plane_state);

	return 0;
}

static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb,
					      struct intel_plane *plane,
					      const struct intel_crtc_state *crtc_state)
{
	struct intel_display *display = to_intel_display(plane);
	enum pipe pipe = plane->pipe;

	if (!crtc_state->enable_psr2_sel_fetch)
		return;

	intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), 0);
}

static void wa_16021440873(struct intel_dsb *dsb,
			   struct intel_plane *plane,
			   const struct intel_crtc_state *crtc_state,
			   const struct intel_plane_state *plane_state)
{
	struct intel_display *display = to_intel_display(plane);
	u32 ctl = plane_state->ctl;
	int et_y_position = drm_rect_height(&crtc_state->pipe_src) + 1;
	enum pipe pipe = plane->pipe;

	ctl &= ~MCURSOR_MODE_MASK;
	ctl |= MCURSOR_MODE_64_2B;

	intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), ctl);

	intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(display, pipe),
			   CURSOR_POS_Y(et_y_position));
}

static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb,
					     struct intel_plane *plane,
					     const struct intel_crtc_state *crtc_state,
					     const struct intel_plane_state *plane_state)
{
	struct intel_display *display = to_intel_display(plane);
	enum pipe pipe = plane->pipe;

	if (!crtc_state->enable_psr2_sel_fetch)
		return;

	if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) {
		if (crtc_state->enable_psr2_su_region_et) {
			u32 val = intel_cursor_position(crtc_state, plane_state,
				true);

			intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(display, pipe), val);
		}

		intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), plane_state->ctl);
	} else {
		/* Wa_16021440873 */
		if (crtc_state->enable_psr2_su_region_et)
			wa_16021440873(dsb, plane, crtc_state, plane_state);
		else
			i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);
	}

Annotation

Implementation Notes