Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37aa2243 authored by Alastair Bridgewater's avatar Alastair Bridgewater Committed by Ben Skeggs
Browse files

drm/nouveau: Handle frame-packing mode geometry and timing effects



Frame-packing modes add an extra vtotal raster lines to each frame
above and beyond what the basic mode description calls for.
Account for this during scaler configuration (possibly a bit of a
hack), during CRTC configuration (clearly not a hack), and when
checking that a mode is valid for a given connector (cribbed from
the i915 driver).

Signed-off-by: default avatarAlastair Bridgewater <alastair.bridgewater@gmail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent a8970743
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1045,6 +1045,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
		return MODE_BAD;
	}

	if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
		clock *= 2;

	if (clock < min_clock)
		return MODE_CLOCK_LOW;

+14 −7
Original line number Diff line number Diff line
@@ -1967,6 +1967,7 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh,
	struct drm_display_mode *umode = &asyh->state.mode;
	int mode = asyc->scaler.mode;
	struct edid *edid;
	int umode_vdisplay, omode_hdisplay, omode_vdisplay;

	if (connector->edid_blob_ptr)
		edid = (struct edid *)connector->edid_blob_ptr->data;
@@ -1981,12 +1982,18 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh,
		mode = DRM_MODE_SCALE_FULLSCREEN;
	}

	/* For the user-specified mode, we must ignore doublescan and
	 * the like, but honor frame packing.
	 */
	umode_vdisplay = umode->vdisplay;
	if ((umode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
		umode_vdisplay += umode->vtotal;
	asyh->view.iW = umode->hdisplay;
	asyh->view.iH = umode->vdisplay;
	asyh->view.oW = omode->hdisplay;
	asyh->view.oH = omode->vdisplay;
	if (omode->flags & DRM_MODE_FLAG_DBLSCAN)
		asyh->view.oH *= 2;
	asyh->view.iH = umode_vdisplay;
	/* For the output mode, we can just use the stock helper. */
	drm_mode_get_hv_timing(omode, &omode_hdisplay, &omode_vdisplay);
	asyh->view.oW = omode_hdisplay;
	asyh->view.oH = omode_vdisplay;

	/* Add overscan compensation if necessary, will keep the aspect
	 * ratio the same as the backend mode unless overridden by the
@@ -2016,7 +2023,7 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh,
	switch (mode) {
	case DRM_MODE_SCALE_CENTER:
		asyh->view.oW = min((u16)umode->hdisplay, asyh->view.oW);
		asyh->view.oH = min((u16)umode->vdisplay, asyh->view.oH);
		asyh->view.oH = min((u16)umode_vdisplay, asyh->view.oH);
		/* fall-through */
	case DRM_MODE_SCALE_ASPECT:
		if (asyh->view.oH < asyh->view.oW) {
@@ -2041,7 +2048,7 @@ nv50_head_atomic_check_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
	struct nv50_head_mode *m = &asyh->mode;
	u32 blankus;

	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);

	/*
	 * DRM modes are defined in terms of a repeating interval