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

Commit 02e546ea authored by Dave Airlie's avatar Dave Airlie
Browse files

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



- fix problem with pascal and large memory systems
- fix a bunch of MST problems
- fix a runtime PM interaction with MST

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv79O8deSts2fxJ_oS6=q8yA+OgwBSEpp5R=BQBmWa+oyg@mail.gmail.com
parents b83ce39b 2f958e82
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -55,6 +55,9 @@ nv04_display_create(struct drm_device *dev)
	nouveau_display(dev)->init = nv04_display_init;
	nouveau_display(dev)->fini = nv04_display_fini;

	/* Pre-nv50 doesn't support atomic, so don't expose the ioctls */
	dev->driver->driver_features &= ~DRIVER_ATOMIC;

	nouveau_hw_save_vga_fonts(dev, 1);

	nv04_crtc_create(dev, 0);
+27 −26
Original line number Diff line number Diff line
@@ -1585,8 +1585,9 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
 *****************************************************************************/

static void
nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock)
nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock)
{
	struct nouveau_drm *drm = nouveau_drm(state->dev);
	struct nv50_disp *disp = nv50_disp(drm->dev);
	struct nv50_core *core = disp->core;
	struct nv50_mstm *mstm;
@@ -1617,6 +1618,22 @@ nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock)
	}
}

static void
nv50_disp_atomic_commit_wndw(struct drm_atomic_state *state, u32 *interlock)
{
	struct drm_plane_state *new_plane_state;
	struct drm_plane *plane;
	int i;

	for_each_new_plane_in_state(state, plane, new_plane_state, i) {
		struct nv50_wndw *wndw = nv50_wndw(plane);
		if (interlock[wndw->interlock.type] & wndw->interlock.data) {
			if (wndw->func->update)
				wndw->func->update(wndw, interlock);
		}
	}
}

static void
nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
{
@@ -1684,7 +1701,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
			help->disable(encoder);
			interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
			if (outp->flush_disable) {
				nv50_disp_atomic_commit_core(drm, interlock);
				nv50_disp_atomic_commit_wndw(state, interlock);
				nv50_disp_atomic_commit_core(state, interlock);
				memset(interlock, 0x00, sizeof(interlock));
			}
		}
@@ -1693,15 +1711,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
	/* Flush disable. */
	if (interlock[NV50_DISP_INTERLOCK_CORE]) {
		if (atom->flush_disable) {
			for_each_new_plane_in_state(state, plane, new_plane_state, i) {
				struct nv50_wndw *wndw = nv50_wndw(plane);
				if (interlock[wndw->interlock.type] & wndw->interlock.data) {
					if (wndw->func->update)
						wndw->func->update(wndw, interlock);
				}
			}

			nv50_disp_atomic_commit_core(drm, interlock);
			nv50_disp_atomic_commit_wndw(state, interlock);
			nv50_disp_atomic_commit_core(state, interlock);
			memset(interlock, 0x00, sizeof(interlock));
		}
	}
@@ -1762,18 +1773,14 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
	}

	/* Flush update. */
	for_each_new_plane_in_state(state, plane, new_plane_state, i) {
		struct nv50_wndw *wndw = nv50_wndw(plane);
		if (interlock[wndw->interlock.type] & wndw->interlock.data) {
			if (wndw->func->update)
				wndw->func->update(wndw, interlock);
		}
	}
	nv50_disp_atomic_commit_wndw(state, interlock);

	if (interlock[NV50_DISP_INTERLOCK_CORE]) {
		if (interlock[NV50_DISP_INTERLOCK_BASE] ||
		    interlock[NV50_DISP_INTERLOCK_OVLY] ||
		    interlock[NV50_DISP_INTERLOCK_WNDW] ||
		    !atom->state.legacy_cursor_update)
			nv50_disp_atomic_commit_core(drm, interlock);
			nv50_disp_atomic_commit_core(state, interlock);
		else
			disp->core->func->update(disp->core, interlock, false);
	}
@@ -1871,7 +1878,7 @@ nv50_disp_atomic_commit(struct drm_device *dev,
		nv50_disp_atomic_commit_tail(state);

	drm_for_each_crtc(crtc, dev) {
		if (crtc->state->enable) {
		if (crtc->state->active) {
			if (!drm->have_disp_power_ref) {
				drm->have_disp_power_ref = true;
				return 0;
@@ -2119,10 +2126,6 @@ nv50_display_destroy(struct drm_device *dev)
	kfree(disp);
}

MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)");
static int nouveau_atomic = 0;
module_param_named(atomic, nouveau_atomic, int, 0400);

int
nv50_display_create(struct drm_device *dev)
{
@@ -2147,8 +2150,6 @@ nv50_display_create(struct drm_device *dev)
	disp->disp = &nouveau_display(dev)->disp;
	dev->mode_config.funcs = &nv50_disp_func;
	dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP;
	if (nouveau_atomic)
		dev->driver->driver_features |= DRIVER_ATOMIC;

	/* small shared memory area we use for notifiers and semaphores */
	ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
+4 −2
Original line number Diff line number Diff line
@@ -267,6 +267,7 @@ nouveau_backlight_init(struct drm_device *dev)
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvif_device *device = &drm->client.device;
	struct drm_connector *connector;
	struct drm_connector_list_iter conn_iter;

	INIT_LIST_HEAD(&drm->bl_connectors);

@@ -275,7 +276,8 @@ nouveau_backlight_init(struct drm_device *dev)
		return 0;
	}

	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	drm_connector_list_iter_begin(dev, &conn_iter);
	drm_for_each_connector_iter(connector, &conn_iter) {
		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
		    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
			continue;
@@ -292,7 +294,7 @@ nouveau_backlight_init(struct drm_device *dev)
			break;
		}
	}

	drm_connector_list_iter_end(&conn_iter);

	return 0;
}
+7 −2
Original line number Diff line number Diff line
@@ -1208,14 +1208,19 @@ nouveau_connector_create(struct drm_device *dev, int index)
	struct nouveau_display *disp = nouveau_display(dev);
	struct nouveau_connector *nv_connector = NULL;
	struct drm_connector *connector;
	struct drm_connector_list_iter conn_iter;
	int type, ret = 0;
	bool dummy;

	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	drm_connector_list_iter_begin(dev, &conn_iter);
	nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
		nv_connector = nouveau_connector(connector);
		if (nv_connector->index == index)
		if (nv_connector->index == index) {
			drm_connector_list_iter_end(&conn_iter);
			return connector;
		}
	}
	drm_connector_list_iter_end(&conn_iter);

	nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
	if (!nv_connector)
+32 −4
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <drm/drm_encoder.h>
#include <drm/drm_dp_helper.h>
#include "nouveau_crtc.h"
#include "nouveau_encoder.h"

struct nvkm_i2c_port;

@@ -60,19 +61,46 @@ static inline struct nouveau_connector *nouveau_connector(
	return container_of(con, struct nouveau_connector, base);
}

static inline bool
nouveau_connector_is_mst(struct drm_connector *connector)
{
	const struct nouveau_encoder *nv_encoder;
	const struct drm_encoder *encoder;

	if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
		return false;

	nv_encoder = find_encoder(connector, DCB_OUTPUT_ANY);
	if (!nv_encoder)
		return false;

	encoder = &nv_encoder->base.base;
	return encoder->encoder_type == DRM_MODE_ENCODER_DPMST;
}

#define nouveau_for_each_non_mst_connector_iter(connector, iter) \
	drm_for_each_connector_iter(connector, iter) \
		for_each_if(!nouveau_connector_is_mst(connector))

static inline struct nouveau_connector *
nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
{
	struct drm_device *dev = nv_crtc->base.dev;
	struct drm_connector *connector;
	struct drm_connector_list_iter conn_iter;
	struct nouveau_connector *nv_connector = NULL;
	struct drm_crtc *crtc = to_drm_crtc(nv_crtc);

	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
		if (connector->encoder && connector->encoder->crtc == crtc)
			return nouveau_connector(connector);
	drm_connector_list_iter_begin(dev, &conn_iter);
	nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
		if (connector->encoder && connector->encoder->crtc == crtc) {
			nv_connector = nouveau_connector(connector);
			break;
		}
	}
	drm_connector_list_iter_end(&conn_iter);

	return NULL;
	return nv_connector;
}

struct drm_connector *
Loading