mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 14:41:39 +00:00
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: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv79O8deSts2fxJ_oS6=q8yA+OgwBSEpp5R=BQBmWa+oyg@mail.gmail.com
This commit is contained in:
commit
02e546eacc
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 *
|
||||
|
@ -404,6 +404,7 @@ nouveau_display_init(struct drm_device *dev)
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
int ret;
|
||||
|
||||
ret = disp->init(dev);
|
||||
@ -411,10 +412,12 @@ nouveau_display_init(struct drm_device *dev)
|
||||
return ret;
|
||||
|
||||
/* enable hotplug interrupts */
|
||||
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) {
|
||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||
nvif_notify_get(&conn->hpd);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
/* enable flip completion events */
|
||||
nvif_notify_get(&drm->flip);
|
||||
@ -427,6 +430,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
|
||||
if (!suspend) {
|
||||
if (drm_drv_uses_atomic_modeset(dev))
|
||||
@ -439,10 +443,12 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
|
||||
nvif_notify_put(&drm->flip);
|
||||
|
||||
/* disable hotplug interrupts */
|
||||
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) {
|
||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||
nvif_notify_put(&conn->hpd);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
disp->fini(dev);
|
||||
|
@ -81,6 +81,10 @@ MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
|
||||
int nouveau_modeset = -1;
|
||||
module_param_named(modeset, nouveau_modeset, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)");
|
||||
static int nouveau_atomic = 0;
|
||||
module_param_named(atomic, nouveau_atomic, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)");
|
||||
static int nouveau_runtime_pm = -1;
|
||||
module_param_named(runpm, nouveau_runtime_pm, int, 0400);
|
||||
@ -509,6 +513,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
if (nouveau_atomic)
|
||||
driver_pci.driver_features |= DRIVER_ATOMIC;
|
||||
|
||||
ret = drm_get_pci_dev(pdev, pent, &driver_pci);
|
||||
if (ret) {
|
||||
nvkm_device_del(&device);
|
||||
@ -874,22 +881,11 @@ nouveau_pmops_runtime_resume(struct device *dev)
|
||||
static int
|
||||
nouveau_pmops_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
struct nouveau_drm *drm = nouveau_drm(drm_dev);
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
if (!nouveau_pmops_runtime()) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
list_for_each_entry(crtc, &drm->dev->mode_config.crtc_list, head) {
|
||||
if (crtc->enabled) {
|
||||
DRM_DEBUG_DRIVER("failing to power off - crtc active\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_autosuspend(dev);
|
||||
/* we don't want the main rpm_idle to call suspend - we want to autosuspend */
|
||||
|
@ -616,7 +616,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
|
||||
struct nouveau_bo *nvbo;
|
||||
uint32_t data;
|
||||
|
||||
if (unlikely(r->bo_index > req->nr_buffers)) {
|
||||
if (unlikely(r->bo_index >= req->nr_buffers)) {
|
||||
NV_PRINTK(err, cli, "reloc bo index invalid\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
@ -626,7 +626,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
|
||||
if (b->presumed.valid)
|
||||
continue;
|
||||
|
||||
if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
|
||||
if (unlikely(r->reloc_bo_index >= req->nr_buffers)) {
|
||||
NV_PRINTK(err, cli, "reloc container bo index invalid\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
@ -140,6 +140,9 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
|
||||
if (fb->func->init)
|
||||
fb->func->init(fb);
|
||||
|
||||
if (fb->func->init_remapper)
|
||||
fb->func->init_remapper(fb);
|
||||
|
||||
if (fb->func->init_page) {
|
||||
ret = fb->func->init_page(fb);
|
||||
if (WARN_ON(ret))
|
||||
|
@ -36,6 +36,14 @@ gp100_fb_init_unkn(struct nvkm_fb *base)
|
||||
nvkm_wr32(device, 0x1faccc, nvkm_rd32(device, 0x100ccc));
|
||||
}
|
||||
|
||||
void
|
||||
gp100_fb_init_remapper(struct nvkm_fb *fb)
|
||||
{
|
||||
struct nvkm_device *device = fb->subdev.device;
|
||||
/* Disable address remapper. */
|
||||
nvkm_mask(device, 0x100c14, 0x00040000, 0x00000000);
|
||||
}
|
||||
|
||||
void
|
||||
gp100_fb_init(struct nvkm_fb *base)
|
||||
{
|
||||
@ -56,6 +64,7 @@ gp100_fb = {
|
||||
.dtor = gf100_fb_dtor,
|
||||
.oneinit = gf100_fb_oneinit,
|
||||
.init = gp100_fb_init,
|
||||
.init_remapper = gp100_fb_init_remapper,
|
||||
.init_page = gm200_fb_init_page,
|
||||
.init_unkn = gp100_fb_init_unkn,
|
||||
.ram_new = gp100_ram_new,
|
||||
|
@ -31,6 +31,7 @@ gp102_fb = {
|
||||
.dtor = gf100_fb_dtor,
|
||||
.oneinit = gf100_fb_oneinit,
|
||||
.init = gp100_fb_init,
|
||||
.init_remapper = gp100_fb_init_remapper,
|
||||
.init_page = gm200_fb_init_page,
|
||||
.ram_new = gp100_ram_new,
|
||||
};
|
||||
|
@ -11,6 +11,7 @@ struct nvkm_fb_func {
|
||||
u32 (*tags)(struct nvkm_fb *);
|
||||
int (*oneinit)(struct nvkm_fb *);
|
||||
void (*init)(struct nvkm_fb *);
|
||||
void (*init_remapper)(struct nvkm_fb *);
|
||||
int (*init_page)(struct nvkm_fb *);
|
||||
void (*init_unkn)(struct nvkm_fb *);
|
||||
void (*intr)(struct nvkm_fb *);
|
||||
@ -69,5 +70,6 @@ int gf100_fb_init_page(struct nvkm_fb *);
|
||||
|
||||
int gm200_fb_init_page(struct nvkm_fb *);
|
||||
|
||||
void gp100_fb_init_remapper(struct nvkm_fb *);
|
||||
void gp100_fb_init_unkn(struct nvkm_fb *);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user