diff options
| -rw-r--r-- | drivers/gpu/drm/nouveau/dispnv04/disp.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/disp.c | 53 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_backlight.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.h | 36 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | 2 |
12 files changed, 105 insertions, 49 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 501d2d290e9c..70dce544984e 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c | |||
| @@ -55,6 +55,9 @@ nv04_display_create(struct drm_device *dev) | |||
| 55 | nouveau_display(dev)->init = nv04_display_init; | 55 | nouveau_display(dev)->init = nv04_display_init; |
| 56 | nouveau_display(dev)->fini = nv04_display_fini; | 56 | nouveau_display(dev)->fini = nv04_display_fini; |
| 57 | 57 | ||
| 58 | /* Pre-nv50 doesn't support atomic, so don't expose the ioctls */ | ||
| 59 | dev->driver->driver_features &= ~DRIVER_ATOMIC; | ||
| 60 | |||
| 58 | nouveau_hw_save_vga_fonts(dev, 1); | 61 | nouveau_hw_save_vga_fonts(dev, 1); |
| 59 | 62 | ||
| 60 | nv04_crtc_create(dev, 0); | 63 | nv04_crtc_create(dev, 0); |
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index b83465ae7c1b..9bae4db84cfb 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c | |||
| @@ -1585,8 +1585,9 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) | |||
| 1585 | *****************************************************************************/ | 1585 | *****************************************************************************/ |
| 1586 | 1586 | ||
| 1587 | static void | 1587 | static void |
| 1588 | nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock) | 1588 | nv50_disp_atomic_commit_core(struct drm_atomic_state *state, u32 *interlock) |
| 1589 | { | 1589 | { |
| 1590 | struct nouveau_drm *drm = nouveau_drm(state->dev); | ||
| 1590 | struct nv50_disp *disp = nv50_disp(drm->dev); | 1591 | struct nv50_disp *disp = nv50_disp(drm->dev); |
| 1591 | struct nv50_core *core = disp->core; | 1592 | struct nv50_core *core = disp->core; |
| 1592 | struct nv50_mstm *mstm; | 1593 | struct nv50_mstm *mstm; |
| @@ -1618,6 +1619,22 @@ nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock) | |||
| 1618 | } | 1619 | } |
| 1619 | 1620 | ||
| 1620 | static void | 1621 | static void |
| 1622 | nv50_disp_atomic_commit_wndw(struct drm_atomic_state *state, u32 *interlock) | ||
| 1623 | { | ||
| 1624 | struct drm_plane_state *new_plane_state; | ||
| 1625 | struct drm_plane *plane; | ||
| 1626 | int i; | ||
| 1627 | |||
| 1628 | for_each_new_plane_in_state(state, plane, new_plane_state, i) { | ||
| 1629 | struct nv50_wndw *wndw = nv50_wndw(plane); | ||
| 1630 | if (interlock[wndw->interlock.type] & wndw->interlock.data) { | ||
| 1631 | if (wndw->func->update) | ||
| 1632 | wndw->func->update(wndw, interlock); | ||
| 1633 | } | ||
| 1634 | } | ||
| 1635 | } | ||
| 1636 | |||
| 1637 | static void | ||
| 1621 | nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) | 1638 | nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) |
| 1622 | { | 1639 | { |
| 1623 | struct drm_device *dev = state->dev; | 1640 | struct drm_device *dev = state->dev; |
| @@ -1684,7 +1701,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) | |||
| 1684 | help->disable(encoder); | 1701 | help->disable(encoder); |
| 1685 | interlock[NV50_DISP_INTERLOCK_CORE] |= 1; | 1702 | interlock[NV50_DISP_INTERLOCK_CORE] |= 1; |
| 1686 | if (outp->flush_disable) { | 1703 | if (outp->flush_disable) { |
| 1687 | nv50_disp_atomic_commit_core(drm, interlock); | 1704 | nv50_disp_atomic_commit_wndw(state, interlock); |
| 1705 | nv50_disp_atomic_commit_core(state, interlock); | ||
| 1688 | memset(interlock, 0x00, sizeof(interlock)); | 1706 | memset(interlock, 0x00, sizeof(interlock)); |
| 1689 | } | 1707 | } |
| 1690 | } | 1708 | } |
| @@ -1693,15 +1711,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) | |||
| 1693 | /* Flush disable. */ | 1711 | /* Flush disable. */ |
| 1694 | if (interlock[NV50_DISP_INTERLOCK_CORE]) { | 1712 | if (interlock[NV50_DISP_INTERLOCK_CORE]) { |
| 1695 | if (atom->flush_disable) { | 1713 | if (atom->flush_disable) { |
| 1696 | for_each_new_plane_in_state(state, plane, new_plane_state, i) { | 1714 | nv50_disp_atomic_commit_wndw(state, interlock); |
| 1697 | struct nv50_wndw *wndw = nv50_wndw(plane); | 1715 | nv50_disp_atomic_commit_core(state, interlock); |
| 1698 | if (interlock[wndw->interlock.type] & wndw->interlock.data) { | ||
| 1699 | if (wndw->func->update) | ||
| 1700 | wndw->func->update(wndw, interlock); | ||
| 1701 | } | ||
| 1702 | } | ||
| 1703 | |||
| 1704 | nv50_disp_atomic_commit_core(drm, interlock); | ||
| 1705 | memset(interlock, 0x00, sizeof(interlock)); | 1716 | memset(interlock, 0x00, sizeof(interlock)); |
| 1706 | } | 1717 | } |
| 1707 | } | 1718 | } |
| @@ -1762,18 +1773,14 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) | |||
| 1762 | } | 1773 | } |
| 1763 | 1774 | ||
| 1764 | /* Flush update. */ | 1775 | /* Flush update. */ |
| 1765 | for_each_new_plane_in_state(state, plane, new_plane_state, i) { | 1776 | nv50_disp_atomic_commit_wndw(state, interlock); |
| 1766 | struct nv50_wndw *wndw = nv50_wndw(plane); | ||
| 1767 | if (interlock[wndw->interlock.type] & wndw->interlock.data) { | ||
| 1768 | if (wndw->func->update) | ||
| 1769 | wndw->func->update(wndw, interlock); | ||
| 1770 | } | ||
| 1771 | } | ||
| 1772 | 1777 | ||
| 1773 | if (interlock[NV50_DISP_INTERLOCK_CORE]) { | 1778 | if (interlock[NV50_DISP_INTERLOCK_CORE]) { |
| 1774 | if (interlock[NV50_DISP_INTERLOCK_BASE] || | 1779 | if (interlock[NV50_DISP_INTERLOCK_BASE] || |
| 1780 | interlock[NV50_DISP_INTERLOCK_OVLY] || | ||
| 1781 | interlock[NV50_DISP_INTERLOCK_WNDW] || | ||
| 1775 | !atom->state.legacy_cursor_update) | 1782 | !atom->state.legacy_cursor_update) |
| 1776 | nv50_disp_atomic_commit_core(drm, interlock); | 1783 | nv50_disp_atomic_commit_core(state, interlock); |
| 1777 | else | 1784 | else |
| 1778 | disp->core->func->update(disp->core, interlock, false); | 1785 | disp->core->func->update(disp->core, interlock, false); |
| 1779 | } | 1786 | } |
| @@ -1871,7 +1878,7 @@ nv50_disp_atomic_commit(struct drm_device *dev, | |||
| 1871 | nv50_disp_atomic_commit_tail(state); | 1878 | nv50_disp_atomic_commit_tail(state); |
| 1872 | 1879 | ||
| 1873 | drm_for_each_crtc(crtc, dev) { | 1880 | drm_for_each_crtc(crtc, dev) { |
| 1874 | if (crtc->state->enable) { | 1881 | if (crtc->state->active) { |
| 1875 | if (!drm->have_disp_power_ref) { | 1882 | if (!drm->have_disp_power_ref) { |
| 1876 | drm->have_disp_power_ref = true; | 1883 | drm->have_disp_power_ref = true; |
| 1877 | return 0; | 1884 | return 0; |
| @@ -2119,10 +2126,6 @@ nv50_display_destroy(struct drm_device *dev) | |||
| 2119 | kfree(disp); | 2126 | kfree(disp); |
| 2120 | } | 2127 | } |
| 2121 | 2128 | ||
| 2122 | MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)"); | ||
| 2123 | static int nouveau_atomic = 0; | ||
| 2124 | module_param_named(atomic, nouveau_atomic, int, 0400); | ||
| 2125 | |||
| 2126 | int | 2129 | int |
| 2127 | nv50_display_create(struct drm_device *dev) | 2130 | nv50_display_create(struct drm_device *dev) |
| 2128 | { | 2131 | { |
| @@ -2147,8 +2150,6 @@ nv50_display_create(struct drm_device *dev) | |||
| 2147 | disp->disp = &nouveau_display(dev)->disp; | 2150 | disp->disp = &nouveau_display(dev)->disp; |
| 2148 | dev->mode_config.funcs = &nv50_disp_func; | 2151 | dev->mode_config.funcs = &nv50_disp_func; |
| 2149 | dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP; | 2152 | dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP; |
| 2150 | if (nouveau_atomic) | ||
| 2151 | dev->driver->driver_features |= DRIVER_ATOMIC; | ||
| 2152 | 2153 | ||
| 2153 | /* small shared memory area we use for notifiers and semaphores */ | 2154 | /* small shared memory area we use for notifiers and semaphores */ |
| 2154 | ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, | 2155 | ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index debbbf0fd4bd..408b955e5c39 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c | |||
| @@ -267,6 +267,7 @@ nouveau_backlight_init(struct drm_device *dev) | |||
| 267 | struct nouveau_drm *drm = nouveau_drm(dev); | 267 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 268 | struct nvif_device *device = &drm->client.device; | 268 | struct nvif_device *device = &drm->client.device; |
| 269 | struct drm_connector *connector; | 269 | struct drm_connector *connector; |
| 270 | struct drm_connector_list_iter conn_iter; | ||
| 270 | 271 | ||
| 271 | INIT_LIST_HEAD(&drm->bl_connectors); | 272 | INIT_LIST_HEAD(&drm->bl_connectors); |
| 272 | 273 | ||
| @@ -275,7 +276,8 @@ nouveau_backlight_init(struct drm_device *dev) | |||
| 275 | return 0; | 276 | return 0; |
| 276 | } | 277 | } |
| 277 | 278 | ||
| 278 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 279 | drm_connector_list_iter_begin(dev, &conn_iter); |
| 280 | drm_for_each_connector_iter(connector, &conn_iter) { | ||
| 279 | if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && | 281 | if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && |
| 280 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) | 282 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) |
| 281 | continue; | 283 | continue; |
| @@ -292,7 +294,7 @@ nouveau_backlight_init(struct drm_device *dev) | |||
| 292 | break; | 294 | break; |
| 293 | } | 295 | } |
| 294 | } | 296 | } |
| 295 | 297 | drm_connector_list_iter_end(&conn_iter); | |
| 296 | 298 | ||
| 297 | return 0; | 299 | return 0; |
| 298 | } | 300 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 7b557c354307..af68eae4c626 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
| @@ -1208,14 +1208,19 @@ nouveau_connector_create(struct drm_device *dev, int index) | |||
| 1208 | struct nouveau_display *disp = nouveau_display(dev); | 1208 | struct nouveau_display *disp = nouveau_display(dev); |
| 1209 | struct nouveau_connector *nv_connector = NULL; | 1209 | struct nouveau_connector *nv_connector = NULL; |
| 1210 | struct drm_connector *connector; | 1210 | struct drm_connector *connector; |
| 1211 | struct drm_connector_list_iter conn_iter; | ||
| 1211 | int type, ret = 0; | 1212 | int type, ret = 0; |
| 1212 | bool dummy; | 1213 | bool dummy; |
| 1213 | 1214 | ||
| 1214 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 1215 | drm_connector_list_iter_begin(dev, &conn_iter); |
| 1216 | nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { | ||
| 1215 | nv_connector = nouveau_connector(connector); | 1217 | nv_connector = nouveau_connector(connector); |
| 1216 | if (nv_connector->index == index) | 1218 | if (nv_connector->index == index) { |
| 1219 | drm_connector_list_iter_end(&conn_iter); | ||
| 1217 | return connector; | 1220 | return connector; |
| 1221 | } | ||
| 1218 | } | 1222 | } |
| 1223 | drm_connector_list_iter_end(&conn_iter); | ||
| 1219 | 1224 | ||
| 1220 | nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); | 1225 | nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); |
| 1221 | if (!nv_connector) | 1226 | if (!nv_connector) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index a4d1a059bd3d..dc7454e7f19a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <drm/drm_encoder.h> | 33 | #include <drm/drm_encoder.h> |
| 34 | #include <drm/drm_dp_helper.h> | 34 | #include <drm/drm_dp_helper.h> |
| 35 | #include "nouveau_crtc.h" | 35 | #include "nouveau_crtc.h" |
| 36 | #include "nouveau_encoder.h" | ||
| 36 | 37 | ||
| 37 | struct nvkm_i2c_port; | 38 | struct nvkm_i2c_port; |
| 38 | 39 | ||
| @@ -60,19 +61,46 @@ static inline struct nouveau_connector *nouveau_connector( | |||
| 60 | return container_of(con, struct nouveau_connector, base); | 61 | return container_of(con, struct nouveau_connector, base); |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 64 | static inline bool | ||
| 65 | nouveau_connector_is_mst(struct drm_connector *connector) | ||
| 66 | { | ||
| 67 | const struct nouveau_encoder *nv_encoder; | ||
| 68 | const struct drm_encoder *encoder; | ||
| 69 | |||
| 70 | if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) | ||
| 71 | return false; | ||
| 72 | |||
| 73 | nv_encoder = find_encoder(connector, DCB_OUTPUT_ANY); | ||
| 74 | if (!nv_encoder) | ||
| 75 | return false; | ||
| 76 | |||
| 77 | encoder = &nv_encoder->base.base; | ||
| 78 | return encoder->encoder_type == DRM_MODE_ENCODER_DPMST; | ||
| 79 | } | ||
| 80 | |||
| 81 | #define nouveau_for_each_non_mst_connector_iter(connector, iter) \ | ||
| 82 | drm_for_each_connector_iter(connector, iter) \ | ||
| 83 | for_each_if(!nouveau_connector_is_mst(connector)) | ||
| 84 | |||
| 63 | static inline struct nouveau_connector * | 85 | static inline struct nouveau_connector * |
| 64 | nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) | 86 | nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) |
| 65 | { | 87 | { |
| 66 | struct drm_device *dev = nv_crtc->base.dev; | 88 | struct drm_device *dev = nv_crtc->base.dev; |
| 67 | struct drm_connector *connector; | 89 | struct drm_connector *connector; |
| 90 | struct drm_connector_list_iter conn_iter; | ||
| 91 | struct nouveau_connector *nv_connector = NULL; | ||
| 68 | struct drm_crtc *crtc = to_drm_crtc(nv_crtc); | 92 | struct drm_crtc *crtc = to_drm_crtc(nv_crtc); |
| 69 | 93 | ||
| 70 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 94 | drm_connector_list_iter_begin(dev, &conn_iter); |
| 71 | if (connector->encoder && connector->encoder->crtc == crtc) | 95 | nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { |
| 72 | return nouveau_connector(connector); | 96 | if (connector->encoder && connector->encoder->crtc == crtc) { |
| 97 | nv_connector = nouveau_connector(connector); | ||
| 98 | break; | ||
| 99 | } | ||
| 73 | } | 100 | } |
| 101 | drm_connector_list_iter_end(&conn_iter); | ||
| 74 | 102 | ||
| 75 | return NULL; | 103 | return nv_connector; |
| 76 | } | 104 | } |
| 77 | 105 | ||
| 78 | struct drm_connector * | 106 | struct drm_connector * |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 774b429142bc..ec7861457b84 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
| @@ -404,6 +404,7 @@ nouveau_display_init(struct drm_device *dev) | |||
| 404 | struct nouveau_display *disp = nouveau_display(dev); | 404 | struct nouveau_display *disp = nouveau_display(dev); |
| 405 | struct nouveau_drm *drm = nouveau_drm(dev); | 405 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 406 | struct drm_connector *connector; | 406 | struct drm_connector *connector; |
| 407 | struct drm_connector_list_iter conn_iter; | ||
| 407 | int ret; | 408 | int ret; |
| 408 | 409 | ||
| 409 | ret = disp->init(dev); | 410 | ret = disp->init(dev); |
| @@ -411,10 +412,12 @@ nouveau_display_init(struct drm_device *dev) | |||
| 411 | return ret; | 412 | return ret; |
| 412 | 413 | ||
| 413 | /* enable hotplug interrupts */ | 414 | /* enable hotplug interrupts */ |
| 414 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 415 | drm_connector_list_iter_begin(dev, &conn_iter); |
| 416 | nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { | ||
| 415 | struct nouveau_connector *conn = nouveau_connector(connector); | 417 | struct nouveau_connector *conn = nouveau_connector(connector); |
| 416 | nvif_notify_get(&conn->hpd); | 418 | nvif_notify_get(&conn->hpd); |
| 417 | } | 419 | } |
| 420 | drm_connector_list_iter_end(&conn_iter); | ||
| 418 | 421 | ||
| 419 | /* enable flip completion events */ | 422 | /* enable flip completion events */ |
| 420 | nvif_notify_get(&drm->flip); | 423 | nvif_notify_get(&drm->flip); |
| @@ -427,6 +430,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend) | |||
| 427 | struct nouveau_display *disp = nouveau_display(dev); | 430 | struct nouveau_display *disp = nouveau_display(dev); |
| 428 | struct nouveau_drm *drm = nouveau_drm(dev); | 431 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 429 | struct drm_connector *connector; | 432 | struct drm_connector *connector; |
| 433 | struct drm_connector_list_iter conn_iter; | ||
| 430 | 434 | ||
| 431 | if (!suspend) { | 435 | if (!suspend) { |
| 432 | if (drm_drv_uses_atomic_modeset(dev)) | 436 | if (drm_drv_uses_atomic_modeset(dev)) |
| @@ -439,10 +443,12 @@ nouveau_display_fini(struct drm_device *dev, bool suspend) | |||
| 439 | nvif_notify_put(&drm->flip); | 443 | nvif_notify_put(&drm->flip); |
| 440 | 444 | ||
| 441 | /* disable hotplug interrupts */ | 445 | /* disable hotplug interrupts */ |
| 442 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 446 | drm_connector_list_iter_begin(dev, &conn_iter); |
| 447 | nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { | ||
| 443 | struct nouveau_connector *conn = nouveau_connector(connector); | 448 | struct nouveau_connector *conn = nouveau_connector(connector); |
| 444 | nvif_notify_put(&conn->hpd); | 449 | nvif_notify_put(&conn->hpd); |
| 445 | } | 450 | } |
| 451 | drm_connector_list_iter_end(&conn_iter); | ||
| 446 | 452 | ||
| 447 | drm_kms_helper_poll_disable(dev); | 453 | drm_kms_helper_poll_disable(dev); |
| 448 | disp->fini(dev); | 454 | disp->fini(dev); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 775443c9af94..f5d3158f0378 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
| @@ -81,6 +81,10 @@ MODULE_PARM_DESC(modeset, "enable driver (default: auto, " | |||
| 81 | int nouveau_modeset = -1; | 81 | int nouveau_modeset = -1; |
| 82 | module_param_named(modeset, nouveau_modeset, int, 0400); | 82 | module_param_named(modeset, nouveau_modeset, int, 0400); |
| 83 | 83 | ||
| 84 | MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)"); | ||
| 85 | static int nouveau_atomic = 0; | ||
| 86 | module_param_named(atomic, nouveau_atomic, int, 0400); | ||
| 87 | |||
| 84 | MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)"); | 88 | MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)"); |
| 85 | static int nouveau_runtime_pm = -1; | 89 | static int nouveau_runtime_pm = -1; |
| 86 | module_param_named(runpm, nouveau_runtime_pm, int, 0400); | 90 | module_param_named(runpm, nouveau_runtime_pm, int, 0400); |
| @@ -509,6 +513,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev, | |||
| 509 | 513 | ||
| 510 | pci_set_master(pdev); | 514 | pci_set_master(pdev); |
| 511 | 515 | ||
| 516 | if (nouveau_atomic) | ||
| 517 | driver_pci.driver_features |= DRIVER_ATOMIC; | ||
| 518 | |||
| 512 | ret = drm_get_pci_dev(pdev, pent, &driver_pci); | 519 | ret = drm_get_pci_dev(pdev, pent, &driver_pci); |
| 513 | if (ret) { | 520 | if (ret) { |
| 514 | nvkm_device_del(&device); | 521 | nvkm_device_del(&device); |
| @@ -874,22 +881,11 @@ nouveau_pmops_runtime_resume(struct device *dev) | |||
| 874 | static int | 881 | static int |
| 875 | nouveau_pmops_runtime_idle(struct device *dev) | 882 | nouveau_pmops_runtime_idle(struct device *dev) |
| 876 | { | 883 | { |
| 877 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 878 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
| 879 | struct nouveau_drm *drm = nouveau_drm(drm_dev); | ||
| 880 | struct drm_crtc *crtc; | ||
| 881 | |||
| 882 | if (!nouveau_pmops_runtime()) { | 884 | if (!nouveau_pmops_runtime()) { |
| 883 | pm_runtime_forbid(dev); | 885 | pm_runtime_forbid(dev); |
| 884 | return -EBUSY; | 886 | return -EBUSY; |
| 885 | } | 887 | } |
| 886 | 888 | ||
| 887 | list_for_each_entry(crtc, &drm->dev->mode_config.crtc_list, head) { | ||
| 888 | if (crtc->enabled) { | ||
| 889 | DRM_DEBUG_DRIVER("failing to power off - crtc active\n"); | ||
| 890 | return -EBUSY; | ||
| 891 | } | ||
| 892 | } | ||
| 893 | pm_runtime_mark_last_busy(dev); | 889 | pm_runtime_mark_last_busy(dev); |
| 894 | pm_runtime_autosuspend(dev); | 890 | pm_runtime_autosuspend(dev); |
| 895 | /* we don't want the main rpm_idle to call suspend - we want to autosuspend */ | 891 | /* we don't want the main rpm_idle to call suspend - we want to autosuspend */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 300daee74209..e6ccafcb9c41 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -616,7 +616,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, | |||
| 616 | struct nouveau_bo *nvbo; | 616 | struct nouveau_bo *nvbo; |
| 617 | uint32_t data; | 617 | uint32_t data; |
| 618 | 618 | ||
| 619 | if (unlikely(r->bo_index > req->nr_buffers)) { | 619 | if (unlikely(r->bo_index >= req->nr_buffers)) { |
| 620 | NV_PRINTK(err, cli, "reloc bo index invalid\n"); | 620 | NV_PRINTK(err, cli, "reloc bo index invalid\n"); |
| 621 | ret = -EINVAL; | 621 | ret = -EINVAL; |
| 622 | break; | 622 | break; |
| @@ -626,7 +626,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, | |||
| 626 | if (b->presumed.valid) | 626 | if (b->presumed.valid) |
| 627 | continue; | 627 | continue; |
| 628 | 628 | ||
| 629 | if (unlikely(r->reloc_bo_index > req->nr_buffers)) { | 629 | if (unlikely(r->reloc_bo_index >= req->nr_buffers)) { |
| 630 | NV_PRINTK(err, cli, "reloc container bo index invalid\n"); | 630 | NV_PRINTK(err, cli, "reloc container bo index invalid\n"); |
| 631 | ret = -EINVAL; | 631 | ret = -EINVAL; |
| 632 | break; | 632 | break; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index 73b5d46104bd..434d2fc5bb1c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | |||
| @@ -140,6 +140,9 @@ nvkm_fb_init(struct nvkm_subdev *subdev) | |||
| 140 | if (fb->func->init) | 140 | if (fb->func->init) |
| 141 | fb->func->init(fb); | 141 | fb->func->init(fb); |
| 142 | 142 | ||
| 143 | if (fb->func->init_remapper) | ||
| 144 | fb->func->init_remapper(fb); | ||
| 145 | |||
| 143 | if (fb->func->init_page) { | 146 | if (fb->func->init_page) { |
| 144 | ret = fb->func->init_page(fb); | 147 | ret = fb->func->init_page(fb); |
| 145 | if (WARN_ON(ret)) | 148 | if (WARN_ON(ret)) |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c index dffe1f5e1071..8205ce436b3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c | |||
| @@ -37,6 +37,14 @@ gp100_fb_init_unkn(struct nvkm_fb *base) | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | void | 39 | void |
| 40 | gp100_fb_init_remapper(struct nvkm_fb *fb) | ||
| 41 | { | ||
| 42 | struct nvkm_device *device = fb->subdev.device; | ||
| 43 | /* Disable address remapper. */ | ||
| 44 | nvkm_mask(device, 0x100c14, 0x00040000, 0x00000000); | ||
| 45 | } | ||
| 46 | |||
| 47 | void | ||
| 40 | gp100_fb_init(struct nvkm_fb *base) | 48 | gp100_fb_init(struct nvkm_fb *base) |
| 41 | { | 49 | { |
| 42 | struct gf100_fb *fb = gf100_fb(base); | 50 | struct gf100_fb *fb = gf100_fb(base); |
| @@ -56,6 +64,7 @@ gp100_fb = { | |||
| 56 | .dtor = gf100_fb_dtor, | 64 | .dtor = gf100_fb_dtor, |
| 57 | .oneinit = gf100_fb_oneinit, | 65 | .oneinit = gf100_fb_oneinit, |
| 58 | .init = gp100_fb_init, | 66 | .init = gp100_fb_init, |
| 67 | .init_remapper = gp100_fb_init_remapper, | ||
| 59 | .init_page = gm200_fb_init_page, | 68 | .init_page = gm200_fb_init_page, |
| 60 | .init_unkn = gp100_fb_init_unkn, | 69 | .init_unkn = gp100_fb_init_unkn, |
| 61 | .ram_new = gp100_ram_new, | 70 | .ram_new = gp100_ram_new, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index b84b9861ef26..b4d74e815674 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | |||
| @@ -31,6 +31,7 @@ gp102_fb = { | |||
| 31 | .dtor = gf100_fb_dtor, | 31 | .dtor = gf100_fb_dtor, |
| 32 | .oneinit = gf100_fb_oneinit, | 32 | .oneinit = gf100_fb_oneinit, |
| 33 | .init = gp100_fb_init, | 33 | .init = gp100_fb_init, |
| 34 | .init_remapper = gp100_fb_init_remapper, | ||
| 34 | .init_page = gm200_fb_init_page, | 35 | .init_page = gm200_fb_init_page, |
| 35 | .ram_new = gp100_ram_new, | 36 | .ram_new = gp100_ram_new, |
| 36 | }; | 37 | }; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index 2857f31466bf..1e4ad61c19e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | |||
| @@ -11,6 +11,7 @@ struct nvkm_fb_func { | |||
| 11 | u32 (*tags)(struct nvkm_fb *); | 11 | u32 (*tags)(struct nvkm_fb *); |
| 12 | int (*oneinit)(struct nvkm_fb *); | 12 | int (*oneinit)(struct nvkm_fb *); |
| 13 | void (*init)(struct nvkm_fb *); | 13 | void (*init)(struct nvkm_fb *); |
| 14 | void (*init_remapper)(struct nvkm_fb *); | ||
| 14 | int (*init_page)(struct nvkm_fb *); | 15 | int (*init_page)(struct nvkm_fb *); |
| 15 | void (*init_unkn)(struct nvkm_fb *); | 16 | void (*init_unkn)(struct nvkm_fb *); |
| 16 | void (*intr)(struct nvkm_fb *); | 17 | void (*intr)(struct nvkm_fb *); |
| @@ -69,5 +70,6 @@ int gf100_fb_init_page(struct nvkm_fb *); | |||
| 69 | 70 | ||
| 70 | int gm200_fb_init_page(struct nvkm_fb *); | 71 | int gm200_fb_init_page(struct nvkm_fb *); |
| 71 | 72 | ||
| 73 | void gp100_fb_init_remapper(struct nvkm_fb *); | ||
| 72 | void gp100_fb_init_unkn(struct nvkm_fb *); | 74 | void gp100_fb_init_unkn(struct nvkm_fb *); |
| 73 | #endif | 75 | #endif |
