Commit cdf1d28c authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'linux-5.5' of git://github.com/skeggsb/linux into drm-fixes



Bunch of random nouveau fixes.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Ben Skeggs <skeggsb@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ <CACAvsv56Am90okV334eXgxDuK228sb9UJxMiOYjNAMShvvv4cg@mail.gmail.com
parents 5ba04748 3d1890ef
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ struct nv50_head_atom {
		u8 nhsync:1;
		u8 nvsync:1;
		u8 depth:4;
		u8 bpc;
	} or;

	/* Currently only used for MST */
+64 −44
Original line number Diff line number Diff line
@@ -326,9 +326,9 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
			 * same size as the native one (e.g. different
			 * refresh rate)
			 */
			if (adjusted_mode->hdisplay == native_mode->hdisplay &&
			    adjusted_mode->vdisplay == native_mode->vdisplay &&
			    adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
			if (mode->hdisplay == native_mode->hdisplay &&
			    mode->vdisplay == native_mode->vdisplay &&
			    mode->type & DRM_MODE_TYPE_DRIVER)
				break;
			mode = native_mode;
			asyc->scaler.full = true;
@@ -353,10 +353,20 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
		       struct drm_crtc_state *crtc_state,
		       struct drm_connector_state *conn_state)
{
	struct nouveau_connector *nv_connector =
		nouveau_connector(conn_state->connector);
	return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
	struct drm_connector *connector = conn_state->connector;
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
	int ret;

	ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
					  nv_connector->native_mode);
	if (ret)
		return ret;

	if (crtc_state->mode_changed || crtc_state->connectors_changed)
		asyh->or.bpc = connector->display_info.bpc;

	return 0;
}

/******************************************************************************
@@ -770,32 +780,54 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
	struct nv50_mstm *mstm = mstc->mstm;
	struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
	int slots;
	int ret;

	ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
					  mstc->native);
	if (ret)
		return ret;

	if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
		return 0;

	if (crtc_state->mode_changed || crtc_state->connectors_changed) {
	/*
		 * When restoring duplicated states, we need to make sure that
		 * the bw remains the same and avoid recalculating it, as the
		 * connector's bpc may have changed after the state was
		 * duplicated
	 * When restoring duplicated states, we need to make sure that the bw
	 * remains the same and avoid recalculating it, as the connector's bpc
	 * may have changed after the state was duplicated
	 */
	if (!state->duplicated) {
			const int bpp = connector->display_info.bpc * 3;
		const int clock = crtc_state->adjusted_mode.clock;

			asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
		/*
		 * XXX: Since we don't use HDR in userspace quite yet, limit
		 * the bpc to 8 to save bandwidth on the topology. In the
		 * future, we'll want to properly fix this by dynamically
		 * selecting the highest possible bpc that would fit in the
		 * topology
		 */
		asyh->or.bpc = min(connector->display_info.bpc, 8U);
		asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3);
	}

		slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
						      mstc->port,
	slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port,
					      asyh->dp.pbn);
	if (slots < 0)
		return slots;

	asyh->dp.tu = slots;

	return 0;
}

	return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
					   mstc->native);
static u8
nv50_dp_bpc_to_depth(unsigned int bpc)
{
	switch (bpc) {
	case  6: return 0x2;
	case  8: return 0x5;
	case 10: /* fall-through */
	default: return 0x6;
	}
}

static void
@@ -808,7 +840,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
	struct nv50_mstm *mstm = NULL;
	struct drm_connector *connector;
	struct drm_connector_list_iter conn_iter;
	u8 proto, depth;
	u8 proto;
	bool r;

	drm_connector_list_iter_begin(encoder->dev, &conn_iter);
@@ -837,14 +869,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
	else
		proto = 0x9;

	switch (mstc->connector.display_info.bpc) {
	case  6: depth = 0x2; break;
	case  8: depth = 0x5; break;
	case 10:
	default: depth = 0x6; break;
	}

	mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
	mstm->outp->update(mstm->outp, head->base.index, armh, proto,
			   nv50_dp_bpc_to_depth(armh->or.bpc));

	msto->head = head;
	msto->mstc = mstc;
@@ -1498,20 +1524,14 @@ nv50_sor_enable(struct drm_encoder *encoder)
					lvds.lvds.script |= 0x0200;
			}

			if (nv_connector->base.display_info.bpc == 8)
			if (asyh->or.bpc == 8)
				lvds.lvds.script |= 0x0200;
		}

		nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
		break;
	case DCB_OUTPUT_DP:
		if (nv_connector->base.display_info.bpc == 6)
			depth = 0x2;
		else
		if (nv_connector->base.display_info.bpc == 8)
			depth = 0x5;
		else
			depth = 0x6;
		depth = nv50_dp_bpc_to_depth(asyh->or.bpc);

		if (nv_encoder->link & 1)
			proto = 0x8;
@@ -1662,7 +1682,7 @@ nv50_pior_enable(struct drm_encoder *encoder)
	nv50_outp_acquire(nv_encoder);

	nv_connector = nouveau_encoder_connector_get(nv_encoder);
	switch (nv_connector->base.display_info.bpc) {
	switch (asyh->or.bpc) {
	case 10: asyh->or.depth = 0x6; break;
	case  8: asyh->or.depth = 0x5; break;
	case  6: asyh->or.depth = 0x2; break;
+2 −3
Original line number Diff line number Diff line
@@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv50_head_atom *armh,
			      struct nv50_head_atom *asyh,
			      struct nouveau_conn_atom *asyc)
{
	struct drm_connector *connector = asyc->state.connector;
	u32 mode = 0x00;

	if (asyc->dither.mode == DITHERING_MODE_AUTO) {
		if (asyh->base.depth > connector->display_info.bpc * 3)
		if (asyh->base.depth > asyh->or.bpc * 3)
			mode = DITHERING_MODE_DYNAMIC2X2;
	} else {
		mode = asyc->dither.mode;
	}

	if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
		if (connector->display_info.bpc >= 8)
		if (asyh->or.bpc >= 8)
			mode |= DITHERING_DEPTH_8BPC;
	} else {
		mode |= asyc->dither.depth;
+21 −7
Original line number Diff line number Diff line
@@ -245,14 +245,22 @@ nouveau_conn_atomic_duplicate_state(struct drm_connector *connector)
void
nouveau_conn_reset(struct drm_connector *connector)
{
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct nouveau_conn_atom *asyc;

	if (drm_drv_uses_atomic_modeset(connector->dev)) {
		if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
			return;

		if (connector->state)
		nouveau_conn_atomic_destroy_state(connector, connector->state);
			nouveau_conn_atomic_destroy_state(connector,
							  connector->state);

		__drm_atomic_helper_connector_reset(connector, &asyc->state);
	} else {
		asyc = &nv_connector->properties_state;
	}

	asyc->dither.mode = DITHERING_MODE_AUTO;
	asyc->dither.depth = DITHERING_DEPTH_AUTO;
	asyc->scaler.mode = DRM_MODE_SCALE_NONE;
@@ -276,8 +284,14 @@ void
nouveau_conn_attach_properties(struct drm_connector *connector)
{
	struct drm_device *dev = connector->dev;
	struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
	struct nouveau_display *disp = nouveau_display(dev);
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct nouveau_conn_atom *armc;

	if (drm_drv_uses_atomic_modeset(connector->dev))
		armc = nouveau_conn_atom(connector->state);
	else
		armc = &nv_connector->properties_state;

	/* Init DVI-I specific properties. */
	if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
@@ -748,9 +762,9 @@ static int
nouveau_connector_set_property(struct drm_connector *connector,
			       struct drm_property *property, uint64_t value)
{
	struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
	struct nouveau_conn_atom *asyc = &nv_connector->properties_state;
	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
	int ret;

+61 −55
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@

#include <nvif/notify.h>

#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder.h>
#include <drm/drm_dp_helper.h>
@@ -44,6 +45,60 @@ struct dcb_output;
struct nouveau_backlight;
#endif

#define nouveau_conn_atom(p)                                                   \
	container_of((p), struct nouveau_conn_atom, state)

struct nouveau_conn_atom {
	struct drm_connector_state state;

	struct {
		/* The enum values specifically defined here match nv50/gf119
		 * hw values, and the code relies on this.
		 */
		enum {
			DITHERING_MODE_OFF = 0x00,
			DITHERING_MODE_ON = 0x01,
			DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
			DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
			DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
			DITHERING_MODE_AUTO
		} mode;
		enum {
			DITHERING_DEPTH_6BPC = 0x00,
			DITHERING_DEPTH_8BPC = 0x02,
			DITHERING_DEPTH_AUTO
		} depth;
	} dither;

	struct {
		int mode;	/* DRM_MODE_SCALE_* */
		struct {
			enum {
				UNDERSCAN_OFF,
				UNDERSCAN_ON,
				UNDERSCAN_AUTO,
			} mode;
			u32 hborder;
			u32 vborder;
		} underscan;
		bool full;
	} scaler;

	struct {
		int color_vibrance;
		int vibrant_hue;
	} procamp;

	union {
		struct {
			bool dither:1;
			bool scaler:1;
			bool procamp:1;
		};
		u8 mask;
	} set;
};

struct nouveau_connector {
	struct drm_connector base;
	enum dcb_connector_type type;
@@ -63,6 +118,12 @@ struct nouveau_connector {
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
	struct nouveau_backlight *backlight;
#endif
	/*
	 * Our connector property code expects a nouveau_conn_atom struct
	 * even on pre-nv50 where we do not support atomic. This embedded
	 * version gets used in the non atomic modeset case.
	 */
	struct nouveau_conn_atom properties_state;
};

static inline struct nouveau_connector *nouveau_connector(
@@ -121,61 +182,6 @@ extern int nouveau_ignorelid;
extern int nouveau_duallink;
extern int nouveau_hdmimhz;

#include <drm/drm_crtc.h>
#define nouveau_conn_atom(p)                                                   \
	container_of((p), struct nouveau_conn_atom, state)

struct nouveau_conn_atom {
	struct drm_connector_state state;

	struct {
		/* The enum values specifically defined here match nv50/gf119
		 * hw values, and the code relies on this.
		 */
		enum {
			DITHERING_MODE_OFF = 0x00,
			DITHERING_MODE_ON = 0x01,
			DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
			DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
			DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
			DITHERING_MODE_AUTO
		} mode;
		enum {
			DITHERING_DEPTH_6BPC = 0x00,
			DITHERING_DEPTH_8BPC = 0x02,
			DITHERING_DEPTH_AUTO
		} depth;
	} dither;

	struct {
		int mode;	/* DRM_MODE_SCALE_* */
		struct {
			enum {
				UNDERSCAN_OFF,
				UNDERSCAN_ON,
				UNDERSCAN_AUTO,
			} mode;
			u32 hborder;
			u32 vborder;
		} underscan;
		bool full;
	} scaler;

	struct {
		int color_vibrance;
		int vibrant_hue;
	} procamp;

	union {
		struct {
			bool dither:1;
			bool scaler:1;
			bool procamp:1;
		};
		u8 mask;
	} set;
};

void nouveau_conn_attach_properties(struct drm_connector *);
void nouveau_conn_reset(struct drm_connector *);
struct drm_connector_state *