aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/Kconfig5
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/arb.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c54
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/cursor.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dac.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dfp.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.h1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/hw.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/hw.h1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/overlay.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv04.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/atom.h14
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base507c.c26
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base827c.c11
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base907c.c65
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base917c.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/corec37d.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c68
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.c18
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly507e.c3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly827e.c3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly907e.c13
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly917e.c5
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.c113
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.h10
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c61
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c72
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c26
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_debugfs.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dmem.c456
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dmem.h11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_hwmon.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ioc32.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_prime.c28
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_svm.c50
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvif/mmu.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c188
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c26
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c3
80 files changed, 967 insertions, 659 deletions
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index 96b9814e6d06..3558df043592 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -86,9 +86,10 @@ config DRM_NOUVEAU_SVM
bool "(EXPERIMENTAL) Enable SVM (Shared Virtual Memory) support"
depends on DEVICE_PRIVATE
depends on DRM_NOUVEAU
- depends on HMM_MIRROR
+ depends on MMU
depends on STAGING
- select MIGRATE_VMA_HELPER
+ select HMM_MIRROR
+ select MMU_NOTIFIER
default n
help
Say Y here if you want to enable experimental support for
diff --git a/drivers/gpu/drm/nouveau/dispnv04/arb.c b/drivers/gpu/drm/nouveau/dispnv04/arb.c
index c79160c37f84..362495535e69 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/arb.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c
@@ -21,8 +21,6 @@
* SOFTWARE.
*/
-#include <drm/drmP.h>
-
#include "nouveau_drv.h"
#include "nouveau_reg.h"
#include "hw.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index f22f01020625..37c50ea8f847 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -22,11 +22,10 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include <linux/pm_runtime.h>
-
-#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h>
+#include <drm/drm_vblank.h>
#include "nouveau_drv.h"
#include "nouveau_reg.h"
@@ -1031,53 +1030,6 @@ nv04_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
return 0;
}
-static int
-nouveau_crtc_set_config(struct drm_mode_set *set,
- struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_device *dev;
- struct nouveau_drm *drm;
- int ret;
- struct drm_crtc *crtc;
- bool active = false;
- if (!set || !set->crtc)
- return -EINVAL;
-
- dev = set->crtc->dev;
-
- /* get a pm reference here */
- ret = pm_runtime_get_sync(dev->dev);
- if (ret < 0 && ret != -EACCES)
- return ret;
-
- ret = drm_crtc_helper_set_config(set, ctx);
-
- drm = nouveau_drm(dev);
-
- /* if we get here with no crtcs active then we can drop a reference */
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- if (crtc->enabled)
- active = true;
- }
-
- pm_runtime_mark_last_busy(dev->dev);
- /* if we have active crtcs and we don't have a power ref,
- take the current one */
- if (active && !drm->have_disp_power_ref) {
- drm->have_disp_power_ref = true;
- return ret;
- }
- /* if we have no active crtcs, then drop the power ref
- we got before */
- if (!active && drm->have_disp_power_ref) {
- pm_runtime_put_autosuspend(dev->dev);
- drm->have_disp_power_ref = false;
- }
- /* drop the power reference we got coming in here */
- pm_runtime_put_autosuspend(dev->dev);
- return ret;
-}
-
struct nv04_page_flip_state {
struct list_head head;
struct drm_pending_vblank_event *event;
@@ -1293,7 +1245,7 @@ static const struct drm_crtc_funcs nv04_crtc_funcs = {
.cursor_set = nv04_crtc_cursor_set,
.cursor_move = nv04_crtc_cursor_move,
.gamma_set = nv_crtc_gamma_set,
- .set_config = nouveau_crtc_set_config,
+ .set_config = drm_crtc_helper_set_config,
.page_flip = nv04_crtc_page_flip,
.destroy = nv_crtc_destroy,
};
diff --git a/drivers/gpu/drm/nouveau/dispnv04/cursor.c b/drivers/gpu/drm/nouveau/dispnv04/cursor.c
index 16e09f6b9113..4c6440d29c3f 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/cursor.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/cursor.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: MIT
-#include <drm/drmP.h>
#include <drm/drm_mode.h>
#include "nouveau_drv.h"
#include "nouveau_reg.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c
index e7af95d37ddb..e8eef88a8382 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dac.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c
@@ -24,7 +24,6 @@
* DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "nouveau_drv.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index 73d41abbb510..f9f4482c79b5 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -24,8 +24,8 @@
* DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fourcc.h>
#include "nouveau_drv.h"
#include "nouveau_reg.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 500ed0e4b044..44ee82d0c9b6 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -22,7 +22,6 @@
* Author: Ben Skeggs
*/
-#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "nouveau_drv.h"
@@ -210,7 +209,7 @@ nv04_display_create(struct drm_device *dev)
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;
+ dev->driver_features &= ~DRIVER_ATOMIC;
/* Request page flip completion event. */
if (drm->nvsw.client) {
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h
index 6ccfc09bcf0f..495d3284e876 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h
@@ -161,7 +161,6 @@ nv_match_device(struct drm_device *dev, unsigned device,
dev->pdev->subsystem_device == sub_device;
}
-#include <subdev/bios.h>
#include <subdev/bios/init.h>
static inline void
diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c
index 0c9bdf023f5b..3fdfafa8b0ad 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/hw.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c
@@ -22,7 +22,6 @@
* SOFTWARE.
*/
-#include <drm/drmP.h>
#include "nouveau_drv.h"
#include "hw.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.h b/drivers/gpu/drm/nouveau/dispnv04/hw.h
index 3a2be47fb4f1..6987e1766cd2 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/hw.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/hw.h
@@ -23,7 +23,6 @@
#ifndef __NOUVEAU_HW_H__
#define __NOUVEAU_HW_H__
-#include <drm/drmP.h>
#include "disp.h"
#include "nvreg.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index df4358e31075..a3a0a73ae8ab 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -23,7 +23,6 @@
* written by Arthur Huillet.
*/
-#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fourcc.h>
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
index 2b83b2c39d1d..2f6d2b6711ab 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
@@ -24,7 +24,6 @@
*
*/
-#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "nouveau_drv.h"
#include "nouveau_encoder.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
index de4490b4ed30..b701a4d8fe76 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
@@ -24,7 +24,6 @@
*
*/
-#include <drm/drmP.h>
#include "nouveau_drv.h"
#include "nouveau_reg.h"
#include "nouveau_encoder.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index 26fd71c06626..03466f04c741 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -24,7 +24,6 @@
*
*/
-#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_probe_helper.h>
#include "nouveau_drv.h"
diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h
index b5fae5ab3fa8..43df86c38f58 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/atom.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h
@@ -185,6 +185,11 @@ struct nv50_wndw_atom {
} xlut;
struct {
+ u32 matrix[12];
+ bool valid;
+ } csc;
+
+ struct {
u8 mode:2;
u8 interval:4;
@@ -216,14 +221,23 @@ struct nv50_wndw_atom {
u16 y;
} point;
+ struct {
+ u8 depth;
+ u8 k1;
+ u8 src_color:4;
+ u8 dst_color:4;
+ } blend;
+
union nv50_wndw_atom_mask {
struct {
bool ntfy:1;
bool sema:1;
bool xlut:1;
+ bool csc:1;
bool image:1;
bool scale:1;
bool point:1;
+ bool blend:1;
};
u8 mask;
} set, clr;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c
index d5e295ca2caa..00a85f1e1a4a 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c
@@ -25,7 +25,9 @@
#include <nvif/event.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h>
+
#include "nouveau_bo.h"
void
@@ -56,12 +58,21 @@ static void
base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
u32 *push;
- if ((push = evo_wait(&wndw->wndw, 10))) {
+ if ((push = evo_wait(&wndw->wndw, 13))) {
evo_mthd(push, 0x0084, 1);
evo_data(push, asyw->image.mode << 8 |
asyw->image.interval << 4);
evo_mthd(push, 0x00c0, 1);
evo_data(push, asyw->image.handle[0]);
+ if (asyw->image.format == 0xca) {
+ evo_mthd(push, 0x0110, 2);
+ evo_data(push, 1);
+ evo_data(push, 0x6400);
+ } else {
+ evo_mthd(push, 0x0110, 2);
+ evo_data(push, 0);
+ evo_data(push, 0);
+ }
evo_mthd(push, 0x0800, 5);
evo_data(push, asyw->image.offset[0] >> 8);
evo_data(push, 0x00000000);
@@ -179,9 +190,6 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
const struct drm_framebuffer *fb = asyw->state.fb;
int ret;
- if (!fb->format->depth)
- return -EINVAL;
-
ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
@@ -200,6 +208,14 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
asyh->base.y = asyw->state.src.y1 >> 16;
asyh->base.w = asyw->state.fb->width;
asyh->base.h = asyw->state.fb->height;
+
+ /* Some newer formats, esp FP16 ones, don't have a
+ * "depth". There's nothing that really makes sense there
+ * either, so just set it to the implicit bit count.
+ */
+ if (!asyh->base.depth)
+ asyh->base.depth = asyh->base.cpp * 8;
+
return 0;
}
@@ -215,6 +231,8 @@ base507c_format[] = {
DRM_FORMAT_ABGR2101010,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_XBGR16161616F,
+ DRM_FORMAT_ABGR16161616F,
0
};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/base827c.c b/drivers/gpu/drm/nouveau/dispnv50/base827c.c
index 73646819a0d6..f4c05949dd62 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base827c.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/base827c.c
@@ -25,12 +25,21 @@ static void
base827c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
u32 *push;
- if ((push = evo_wait(&wndw->wndw, 10))) {
+ if ((push = evo_wait(&wndw->wndw, 13))) {
evo_mthd(push, 0x0084, 1);
evo_data(push, asyw->image.mode << 8 |
asyw->image.interval << 4);
evo_mthd(push, 0x00c0, 1);
evo_data(push, asyw->image.handle[0]);
+ if (asyw->image.format == 0xca) {
+ evo_mthd(push, 0x0110, 2);
+ evo_data(push, 1);
+ evo_data(push, 0x6400);
+ } else {
+ evo_mthd(push, 0x0110, 2);
+ evo_data(push, 0);
+ evo_data(push, 0);
+ }
evo_mthd(push, 0x0800, 5);
evo_data(push, asyw->image.offset[0] >> 8);
evo_data(push, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c
index 049ce6da321c..5f2de77e0f32 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base907c.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c
@@ -83,6 +83,68 @@ base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
asyw->xlut.i.load = head907d_olut_load;
}
+static inline u32
+csc_drm_to_base(u64 in)
+{
+ /* base takes a 19-bit 2's complement value in S3.16 format */
+ bool sign = in & BIT_ULL(63);
+ u32 integer = (in >> 32) & 0x7fffffff;
+ u32 fraction = in & 0xffffffff;
+
+ if (integer >= 4) {
+ return (1 << 18) - (sign ? 0 : 1);
+ } else {
+ u32 ret = (integer << 16) | (fraction >> 16);
+ if (sign)
+ ret = -ret;
+ return ret & GENMASK(18, 0);
+ }
+}
+
+void
+base907c_csc(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ const struct drm_color_ctm *ctm)
+{
+ int i, j;
+
+ for (j = 0; j < 3; j++) {
+ for (i = 0; i < 4; i++) {
+ u32 *val = &asyw->csc.matrix[j * 4 + i];
+ /* DRM does not support constant offset, while
+ * HW CSC does. Skip it. */
+ if (i == 3) {
+ *val = 0;
+ } else {
+ *val = csc_drm_to_base(ctm->matrix[j * 3 + i]);
+ }
+ }
+ }
+}
+
+static void
+base907c_csc_clr(struct nv50_wndw *wndw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 2))) {
+ evo_mthd(push, 0x0140, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+static void
+base907c_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push, i;
+ if ((push = evo_wait(&wndw->wndw, 13))) {
+ evo_mthd(push, 0x0140, 12);
+ evo_data(push, asyw->csc.matrix[0] | 0x80000000);
+ for (i = 1; i < 12; i++)
+ evo_data(push, asyw->csc.matrix[i]);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
const struct nv50_wndw_func
base907c = {
.acquire = base507c_acquire,
@@ -94,6 +156,9 @@ base907c = {
.ntfy_clr = base507c_ntfy_clr,
.ntfy_wait_begun = base507c_ntfy_wait_begun,
.ilut = base907c_ilut,
+ .csc = base907c_csc,
+ .csc_set = base907c_csc_set,
+ .csc_clr = base907c_csc_clr,
.olut_core = true,
.xlut_set = base907c_xlut_set,
.xlut_clr = base907c_xlut_clr,
diff --git a/drivers/gpu/drm/nouveau/dispnv50/base917c.c b/drivers/gpu/drm/nouveau/dispnv50/base917c.c
index 54d705bb81a5..a1baed4fe0e9 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base917c.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/base917c.c
@@ -36,6 +36,8 @@ base917c_format[] = {
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XRGB2101010,
DRM_FORMAT_ARGB2101010,
+ DRM_FORMAT_XBGR16161616F,
+ DRM_FORMAT_ABGR16161616F,
0
};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c
index 7860774b65bc..40d9b654ab8c 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c
@@ -82,7 +82,7 @@ corec37d_init(struct nv50_core *core)
for (i = 0; i < windows; i++) {
evo_mthd(push, 0x1000 + (i * 0x080), 3);
evo_data(push, i >> 1);
- evo_data(push, 0x00000017);
+ evo_data(push, 0x0000001f);
evo_data(push, 0x00000000);
evo_mthd(push, 0x1010 + (i * 0x080), 1);
evo_data(push, 0x00127fff);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index d866cadd2ef3..a13924ae1992 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -30,14 +30,14 @@
#include <linux/dma-mapping.h>
#include <linux/hdmi.h>
-#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_dp_helper.h>
+#include <drm/drm_edid.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_scdc_helper.h>
-#include <drm/drm_edid.h>
+#include <drm/drm_vblank.h>
#include <nvif/class.h>
#include <nvif/cl0002.h>
@@ -771,16 +771,20 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
int slots;
- /* 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)
- asyh->dp.pbn =
- drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
- connector->display_info.bpc * 3);
+ 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
+ */
+ 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);
+ }
- if (drm_atomic_crtc_needs_modeset(crtc_state)) {
slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
mstc->port,
asyh->dp.pbn);
@@ -1599,7 +1603,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
nv_encoder->aux = aux;
}
- if ((data = nvbios_dp_table(bios, &ver, &hdr, &cnt, &len)) &&
+ if (nv_connector->type != DCB_CONNECTOR_eDP &&
+ (data = nvbios_dp_table(bios, &ver, &hdr, &cnt, &len)) &&
ver >= 0x40 && (nvbios_rd08(bios, data + 0x08) & 0x04)) {
ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16,
nv_connector->base.base.id,
@@ -1826,8 +1831,11 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
NV_ATOMIC(drm, "%s: clr %04x (set %04x)\n", crtc->name,
asyh->clr.mask, asyh->set.mask);
- if (old_crtc_state->active && !new_crtc_state->active)
+
+ if (old_crtc_state->active && !new_crtc_state->active) {
+ pm_runtime_put_noidle(dev->dev);
drm_crtc_vblank_off(crtc);
+ }
if (asyh->clr.mask) {
nv50_head_flush_clr(head, asyh, atom->flush_disable);
@@ -1913,8 +1921,10 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
}
if (new_crtc_state->active) {
- if (!old_crtc_state->active)
+ if (!old_crtc_state->active) {
drm_crtc_vblank_on(crtc);
+ pm_runtime_get_noresume(dev->dev);
+ }
if (new_crtc_state->event)
drm_crtc_vblank_get(crtc);
}
@@ -1979,6 +1989,10 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_cleanup_planes(dev, state);
drm_atomic_helper_commit_cleanup_done(state);
drm_atomic_state_put(state);
+
+ /* Drop the RPM ref we got from nv50_disp_atomic_commit() */
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_runtime_put_autosuspend(dev->dev);
}
static void
@@ -1993,11 +2007,8 @@ static int
nv50_disp_atomic_commit(struct drm_device *dev,
struct drm_atomic_state *state, bool nonblock)
{
- struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_plane_state *new_plane_state;
struct drm_plane *plane;
- struct drm_crtc *crtc;
- bool active = false;
int ret, i;
ret = pm_runtime_get_sync(dev->dev);
@@ -2034,27 +2045,17 @@ nv50_disp_atomic_commit(struct drm_device *dev,
drm_atomic_state_get(state);
+ /*
+ * Grab another RPM ref for the commit tail, which will release the
+ * ref when it's finished
+ */
+ pm_runtime_get_noresume(dev->dev);
+
if (nonblock)
queue_work(system_unbound_wq, &state->commit_work);
else
nv50_disp_atomic_commit_tail(state);
- drm_for_each_crtc(crtc, dev) {
- if (crtc->state->active) {
- if (!drm->have_disp_power_ref) {
- drm->have_disp_power_ref = true;
- return 0;
- }
- active = true;
- break;
- }
- }
-
- if (!active && drm->have_disp_power_ref) {
- pm_runtime_put_autosuspend(dev->dev);
- drm->have_disp_power_ref = false;
- }
-
err_cleanup:
if (ret)
drm_atomic_helper_cleanup_planes(dev, state);
@@ -2316,6 +2317,7 @@ nv50_display_create(struct drm_device *dev)
disp->disp = &nouveau_display(dev)->disp;
dev->mode_config.funcs = &nv50_disp_func;
dev->mode_config.quirk_addfb_prefer_xbgr_30bpp = true;
+ dev->mode_config.normalize_zpos = true;
/* small shared memory area we use for notifiers and semaphores */
ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index 929d93b1677e..71c23bf1fe25 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -480,7 +480,7 @@ nv50_head_create(struct drm_device *dev, int index)
struct nouveau_drm *drm = nouveau_drm(dev);
struct nv50_disp *disp = nv50_disp(dev);
struct nv50_head *head;
- struct nv50_wndw *curs, *wndw;
+ struct nv50_wndw *base, *ovly, *curs;
struct drm_crtc *crtc;
int ret;
@@ -492,13 +492,13 @@ nv50_head_create(struct drm_device *dev, int index)
head->base.index = index;
if (disp->disp->object.oclass < GV100_DISP) {
- ret = nv50_ovly_new(drm, head->base.index, &wndw);
- ret = nv50_base_new(drm, head->base.index, &wndw);
+ ret = nv50_base_new(drm, head->base.index, &base);
+ ret = nv50_ovly_new(drm, head->base.index, &ovly);
} else {
- ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_OVERLAY,
- head->base.index * 2 + 1, &wndw);
ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_PRIMARY,
- head->base.index * 2 + 0, &wndw);
+ head->base.index * 2 + 0, &base);
+ ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_OVERLAY,
+ head->base.index * 2 + 1, &ovly);
}
if (ret == 0)
ret = nv50_curs_new(drm, head->base.index, &curs);
@@ -508,10 +508,14 @@ nv50_head_create(struct drm_device *dev, int index)
}
crtc = &head->base.base;
- drm_crtc_init_with_planes(dev, crtc, &wndw->plane, &curs->plane,
+ drm_crtc_init_with_planes(dev, crtc, &base->plane, &curs->plane,
&nv50_head_func, "head-%d", head->base.index);
drm_crtc_helper_add(crtc, &nv50_head_help);
drm_mode_crtc_set_gamma_size(crtc, 256);
+ if (disp->disp->object.oclass >= GF110_DISP)
+ drm_crtc_enable_color_mgmt(crtc, 256, true, 256);
+ else
+ drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
if (head->func->olut_set) {
ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
index cc417664f823..8ccd96113bad 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
@@ -23,6 +23,7 @@
#include "atom.h"
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h>
#include <nvif/cl507e.h>
@@ -160,9 +161,7 @@ ovly507e_format[] = {
DRM_FORMAT_YUYV,
DRM_FORMAT_UYVY,
DRM_FORMAT_XRGB8888,
- DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB1555,
- DRM_FORMAT_ARGB1555,
0
};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c
index aaa9fe5a4fc8..2e68fc736fe1 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c
@@ -90,11 +90,8 @@ ovly827e_format[] = {
DRM_FORMAT_YUYV,
DRM_FORMAT_UYVY,
DRM_FORMAT_XRGB8888,
- DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB1555,
- DRM_FORMAT_ARGB1555,
DRM_FORMAT_XBGR2101010,
- DRM_FORMAT_ABGR2101010,
0
};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
index a3ce53046015..9efe5e9d5ce4 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
@@ -61,10 +61,21 @@ ovly907e = {
.update = ovly507e_update,
};
+static const u32
+ovly907e_format[] = {
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_UYVY,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_XBGR2101010,
+ DRM_FORMAT_XBGR16161616F,
+ 0
+};
+
int
ovly907e_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw)
{
- return ovly507e_new_(&ovly907e, ovly827e_format, drm, head, oclass,
+ return ovly507e_new_(&ovly907e, ovly907e_format, drm, head, oclass,
0x00000004 << (head * 4), pwndw);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
index 505fa7e78523..e24d6fd23450 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
@@ -26,13 +26,10 @@ ovly917e_format[] = {
DRM_FORMAT_YUYV,
DRM_FORMAT_UYVY,
DRM_FORMAT_XRGB8888,
- DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB1555,
- DRM_FORMAT_ARGB1555,
DRM_FORMAT_XBGR2101010,
- DRM_FORMAT_ABGR2101010,
DRM_FORMAT_XRGB2101010,
- DRM_FORMAT_ARGB2101010,
+ DRM_FORMAT_XBGR16161616F,
0
};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index 027a01b97d1c..5193b6257061 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -26,6 +26,8 @@
#include <nvif/cl0002.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
+
#include "nouveau_bo.h"
static void
@@ -118,6 +120,7 @@ nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 *interlock, bool flush,
if (clr.sema ) wndw->func-> sema_clr(wndw);
if (clr.ntfy ) wndw->func-> ntfy_clr(wndw);
if (clr.xlut ) wndw->func-> xlut_clr(wndw);
+ if (clr.csc ) wndw->func-> csc_clr(wndw);
if (clr.image) wndw->func->image_clr(wndw);
interlock[wndw->interlock.type] |= wndw->interlock.data;
@@ -145,7 +148,9 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
wndw->func->xlut_set(wndw, asyw);
}
+ if (asyw->set.csc ) wndw->func->csc_set (wndw, asyw);
if (asyw->set.scale) wndw->func->scale_set(wndw, asyw);
+ if (asyw->set.blend) wndw->func->blend_set(wndw, asyw);
if (asyw->set.point) {
if (asyw->set.point = false, asyw->set.mask)
interlock[wndw->interlock.type] |= wndw->interlock.data;
@@ -202,18 +207,20 @@ static int
nv50_wndw_atomic_check_acquire_rgb(struct nv50_wndw_atom *asyw)
{
switch (asyw->state.fb->format->format) {
- case DRM_FORMAT_C8 : asyw->image.format = 0x1e; break;
- case DRM_FORMAT_XRGB8888 :
- case DRM_FORMAT_ARGB8888 : asyw->image.format = 0xcf; break;
- case DRM_FORMAT_RGB565 : asyw->image.format = 0xe8; break;
- case DRM_FORMAT_XRGB1555 :
- case DRM_FORMAT_ARGB1555 : asyw->image.format = 0xe9; break;
- case DRM_FORMAT_XBGR2101010:
- case DRM_FORMAT_ABGR2101010: asyw->image.format = 0xd1; break;
- case DRM_FORMAT_XBGR8888 :
- case DRM_FORMAT_ABGR8888 : asyw->image.format = 0xd5; break;
- case DRM_FORMAT_XRGB2101010:
- case DRM_FORMAT_ARGB2101010: asyw->image.format = 0xdf; break;
+ case DRM_FORMAT_C8 : asyw->image.format = 0x1e; break;
+ case DRM_FORMAT_XRGB8888 :
+ case DRM_FORMAT_ARGB8888 : asyw->image.format = 0xcf; break;
+ case DRM_FORMAT_RGB565 : asyw->image.format = 0xe8; break;
+ case DRM_FORMAT_XRGB1555 :
+ case DRM_FORMAT_ARGB1555 : asyw->image.format = 0xe9; break;
+ case DRM_FORMAT_XBGR2101010 :
+ case DRM_FORMAT_ABGR2101010 : asyw->image.format = 0xd1; break;
+ case DRM_FORMAT_XBGR8888 :
+ case DRM_FORMAT_ABGR8888 : asyw->image.format = 0xd5; break;
+ case DRM_FORMAT_XRGB2101010 :
+ case DRM_FORMAT_ARGB2101010 : asyw->image.format = 0xdf; break;
+ case DRM_FORMAT_XBGR16161616F:
+ case DRM_FORMAT_ABGR16161616F: asyw->image.format = 0xca; break;
default:
return -EINVAL;
}
@@ -260,7 +267,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset,
asyw->image.pitch[0] = fb->base.pitches[0];
}
- if (!(asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC))
+ if (!asyh->state.async_flip)
asyw->image.interval = 1;
else
asyw->image.interval = 0;
@@ -279,6 +286,28 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset,
asyw->set.scale = true;
}
+ if (wndw->func->blend_set) {
+ asyw->blend.depth = 255 - asyw->state.normalized_zpos;
+ asyw->blend.k1 = asyw->state.alpha >> 8;
+ switch (asyw->state.pixel_blend_mode) {
+ case DRM_MODE_BLEND_PREMULTI:
+ asyw->blend.src_color = 2; /* K1 */
+ asyw->blend.dst_color = 7; /* NEG_K1_TIMES_SRC */
+ break;
+ case DRM_MODE_BLEND_COVERAGE:
+ asyw->blend.src_color = 5; /* K1_TIMES_SRC */
+ asyw->blend.dst_color = 7; /* NEG_K1_TIMES_SRC */
+ break;
+ case DRM_MODE_BLEND_PIXEL_NONE:
+ default:
+ asyw->blend.src_color = 2; /* K1 */
+ asyw->blend.dst_color = 4; /* NEG_K1 */
+ break;
+ }
+ if (memcmp(&armw->blend, &asyw->blend, sizeof(asyw->blend)))
+ asyw->set.blend = true;
+ }
+
if (wndw->immd) {
asyw->point.x = asyw->state.crtc_x;
asyw->point.y = asyw->state.crtc_y;
@@ -320,7 +349,9 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
asyh->wndw.olut &= ~BIT(wndw->id);
}
- if (!ilut && wndw->func->ilut_identity) {
+ if (!ilut && wndw->func->ilut_identity &&
+ asyw->state.fb->format->format != DRM_FORMAT_XBGR16161616F &&
+ asyw->state.fb->format->format != DRM_FORMAT_ABGR16161616F) {
static struct drm_property_blob dummy = {};
ilut = &dummy;
}
@@ -332,6 +363,8 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
asyw->xlut.handle = wndw->wndw.vram.handle;
asyw->xlut.i.buffer = !asyw->xlut.i.buffer;
asyw->set.xlut = true;
+ } else {
+ asyw->clr.xlut = armw->xlut.handle != 0;
}
/* Handle setting base SET_OUTPUT_LUT_LO_ENABLE_USE_CORE_LUT. */
@@ -339,8 +372,18 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
(!armw->visible || (armw->xlut.handle && !asyw->xlut.handle)))
asyw->set.xlut = true;
+ if (wndw->func->csc && asyh->state.ctm) {
+ const struct drm_color_ctm *ctm = asyh->state.ctm->data;
+ wndw->func->csc(wndw, asyw, ctm);
+ asyw->csc.valid = true;
+ asyw->set.csc = true;
+ } else {
+ asyw->csc.valid = false;
+ asyw->clr.csc = armw->csc.valid;
+ }
+
/* Can't do an immediate flip while changing the LUT. */
- asyh->state.pageflip_flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
+ asyh->state.async_flip = false;
}
static int
@@ -408,6 +451,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
asyw->clr.ntfy = armw->ntfy.handle != 0;
asyw->clr.sema = armw->sema.handle != 0;
asyw->clr.xlut = armw->xlut.handle != 0;
+ asyw->clr.csc = armw->csc.valid;
if (wndw->func->image_clr)
asyw->clr.image = armw->image.handle[0] != 0;
}
@@ -499,6 +543,7 @@ nv50_wndw_atomic_duplicate_state(struct drm_plane *plane)
asyw->ntfy = armw->ntfy;
asyw->ilut = NULL;
asyw->xlut = armw->xlut;
+ asyw->csc = armw->csc;
asyw->image = armw->image;
asyw->point = armw->point;
asyw->clr.mask = 0;
@@ -506,6 +551,13 @@ nv50_wndw_atomic_duplicate_state(struct drm_plane *plane)
return &asyw->state;
}
+static int
+nv50_wndw_zpos_default(struct drm_plane *plane)
+{
+ return (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 :
+ (plane->type == DRM_PLANE_TYPE_OVERLAY) ? 1 : 255;
+}
+
static void
nv50_wndw_reset(struct drm_plane *plane)
{
@@ -516,9 +568,10 @@ nv50_wndw_reset(struct drm_plane *plane)
if (plane->state)
plane->funcs->atomic_destroy_state(plane, plane->state);
- plane->state = &asyw->state;
- plane->state->plane = plane;
- plane->state->rotation = DRM_MODE_ROTATE_0;
+
+ __drm_atomic_helper_plane_reset(plane, &asyw->state);
+ plane->state->zpos = nv50_wndw_zpos_default(plane);
+ plane->state->normalized_zpos = nv50_wndw_zpos_default(plane);
}
static void
@@ -613,6 +666,30 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
}
wndw->notify.func = nv50_wndw_notify;
+
+ if (wndw->func->blend_set) {
+ ret = drm_plane_create_zpos_property(&wndw->plane,
+ nv50_wndw_zpos_default(&wndw->plane), 0, 254);
+ if (ret)
+ return ret;
+
+ ret = drm_plane_create_alpha_property(&wndw->plane);
+ if (ret)
+ return ret;
+
+ ret = drm_plane_create_blend_mode_property(&wndw->plane,
+ BIT(DRM_MODE_BLEND_PIXEL_NONE) |
+ BIT(DRM_MODE_BLEND_PREMULTI) |
+ BIT(DRM_MODE_BLEND_COVERAGE));
+ if (ret)
+ return ret;
+ } else {
+ ret = drm_plane_create_zpos_immutable_property(&wndw->plane,
+ nv50_wndw_zpos_default(&wndw->plane));
+ if (ret)
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
index 03f3d8dc235a..c63bd3bdaf06 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
@@ -65,6 +65,10 @@ struct nv50_wndw_func {
int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset,
struct nvif_device *);
void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ void (*csc)(struct nv50_wndw *, struct nv50_wndw_atom *,
+ const struct drm_color_ctm *);
+ void (*csc_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ void (*csc_clr)(struct nv50_wndw *);
bool ilut_identity;
bool olut_core;
void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
@@ -72,6 +76,7 @@ struct nv50_wndw_func {
void (*image_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
void (*image_clr)(struct nv50_wndw *);
void (*scale_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ void (*blend_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
void (*update)(struct nv50_wndw *, u32 *interlock);
};
@@ -81,6 +86,9 @@ extern const struct drm_plane_funcs nv50_wndw;
void base507c_ntfy_reset(struct nouveau_bo *, u32);
int base507c_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *);
+void base907c_csc(struct nv50_wndw *, struct nv50_wndw_atom *,
+ const struct drm_color_ctm *);
+
struct nv50_wimm_func {
void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *);
@@ -102,8 +110,8 @@ void wndwc37e_sema_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void wndwc37e_sema_clr(struct nv50_wndw *);
void wndwc37e_ntfy_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void wndwc37e_ntfy_clr(struct nv50_wndw *);
-void wndwc37e_image_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void wndwc37e_image_clr(struct nv50_wndw *);
+void wndwc37e_blend_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void wndwc37e_update(struct nv50_wndw *, u32 *);
int wndwc57e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
index e52a85c83f7a..0f9402162bde 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
@@ -29,6 +29,23 @@
#include <nvif/clc37e.h>
static void
+wndwc37e_csc_clr(struct nv50_wndw *wndw)
+{
+}
+
+static void
+wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push, i;
+ if ((push = evo_wait(&wndw->wndw, 13))) {
+ evo_mthd(push, 0x02bc, 12);
+ for (i = 0; i < 12; i++)
+ evo_data(push, asyw->csc.matrix[i]);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+static void
wndwc37e_ilut_clr(struct nv50_wndw *wndw)
{
u32 *push;
@@ -65,6 +82,26 @@ wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
}
void
+wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 8))) {
+ evo_mthd(push, 0x02ec, 7);
+ evo_data(push, asyw->blend.depth << 4);
+ evo_data(push, asyw->blend.k1);
+ evo_data(push, asyw->blend.dst_color << 12 |
+ asyw->blend.dst_color << 8 |
+ asyw->blend.src_color << 4 |
+ asyw->blend.src_color);
+ evo_data(push, 0xffff0000);
+ evo_data(push, 0xffff0000);
+ evo_data(push, 0xffff0000);
+ evo_data(push, 0xffff0000);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+void
wndwc37e_image_clr(struct nv50_wndw *wndw)
{
u32 *push;
@@ -77,12 +114,12 @@ wndwc37e_image_clr(struct nv50_wndw *wndw)
}
}
-void
+static void
wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
u32 *push;
- if (!(push = evo_wait(&wndw->wndw, 25)))
+ if (!(push = evo_wait(&wndw->wndw, 17)))
return;
evo_mthd(push, 0x0308, 1);
@@ -90,7 +127,9 @@ wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
evo_mthd(push, 0x0224, 4);
evo_data(push, asyw->image.h << 16 | asyw->image.w);
evo_data(push, asyw->image.layout << 4 | asyw->image.blockh);
- evo_data(push, asyw->image.colorspace << 8 | asyw->image.format);
+ evo_data(push, asyw->csc.valid << 17 |
+ asyw->image.colorspace << 8 |
+ asyw->image.format);
evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6));
evo_mthd(push, 0x0240, 1);
evo_data(push, asyw->image.handle[0]);
@@ -105,16 +144,6 @@ wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
evo_mthd(push, 0x02a4, 1);
evo_data(push, asyw->state.crtc_h << 16 |
asyw->state.crtc_w);
-
- /*XXX: Composition-related stuff. Need to implement properly. */
- evo_mthd(push, 0x02ec, 1);
- evo_data(push, (2 - (wndw->id & 1)) << 4);
- evo_mthd(push, 0x02f4, 5);
- evo_data(push, 0x00000011);
- evo_data(push, 0xffff0000);
- evo_data(push, 0xffff0000);
- evo_data(push, 0xffff0000);
- evo_data(push, 0xffff0000);
evo_kick(push, &wndw->wndw);
}
@@ -216,6 +245,8 @@ wndwc37e_format[] = {
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XRGB2101010,
DRM_FORMAT_ARGB2101010,
+ DRM_FORMAT_XBGR16161616F,
+ DRM_FORMAT_ABGR16161616F,
0
};
@@ -232,8 +263,12 @@ wndwc37e = {
.ilut = wndwc37e_ilut,
.xlut_set = wndwc37e_ilut_set,
.xlut_clr = wndwc37e_ilut_clr,
+ .csc = base907c_csc,
+ .csc_set = wndwc37e_csc_set,
+ .csc_clr = wndwc37e_csc_clr,
.image_set = wndwc37e_image_set,
.image_clr = wndwc37e_image_clr,
+ .blend_set = wndwc37e_blend_set,
.update = wndwc37e_update,
};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
index ba89f1a5fcfa..a311c79e5295 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
@@ -29,6 +29,72 @@
#include <nvif/clc37e.h>
static void
+wndwc57e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push;
+
+ if (!(push = evo_wait(&wndw->wndw, 17)))
+ return;
+
+ evo_mthd(push, 0x0308, 1);
+ evo_data(push, asyw->image.mode << 4 | asyw->image.interval);
+ evo_mthd(push, 0x0224, 4);
+ evo_data(push, asyw->image.h << 16 | asyw->image.w);
+ evo_data(push, asyw->image.layout << 4 | asyw->image.blockh);
+ evo_data(push, asyw->image.colorspace << 8 |
+ asyw->image.format);
+ evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6));
+ evo_mthd(push, 0x0240, 1);
+ evo_data(push, asyw->image.handle[0]);
+ evo_mthd(push, 0x0260, 1);
+ evo_data(push, asyw->image.offset[0] >> 8);
+ evo_mthd(push, 0x0290, 1);
+ evo_data(push, (asyw->state.src_y >> 16) << 16 |
+ (asyw->state.src_x >> 16));
+ evo_mthd(push, 0x0298, 1);
+ evo_data(push, (asyw->state.src_h >> 16) << 16 |
+ (asyw->state.src_w >> 16));
+ evo_mthd(push, 0x02a4, 1);
+ evo_data(push, asyw->state.crtc_h << 16 |
+ asyw->state.crtc_w);
+ evo_kick(push, &wndw->wndw);
+}
+
+static void
+wndwc57e_csc_clr(struct nv50_wndw *wndw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 13))) {
+ evo_mthd(push, 0x0400, 12);
+ evo_data(push, 0x00010000);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00010000);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00010000);
+ evo_data(push, 0x00000000);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+static void
+wndwc57e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push, i;
+ if ((push = evo_wait(&wndw->wndw, 13))) {
+ evo_mthd(push, 0x0400, 12);
+ for (i = 0; i < 12; i++)
+ evo_data(push, asyw->csc.matrix[i]);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+static void
wndwc57e_ilut_clr(struct nv50_wndw *wndw)
{
u32 *push;
@@ -119,8 +185,12 @@ wndwc57e = {
.ilut_identity = true,
.xlut_set = wndwc57e_ilut_set,
.xlut_clr = wndwc57e_ilut_clr,
- .image_set = wndwc37e_image_set,
+ .csc = base907c_csc,
+ .csc_set = wndwc57e_csc_set,
+ .csc_clr = wndwc57e_csc_clr,
+ .image_set = wndwc57e_image_set,
.image_clr = wndwc37e_image_clr,
+ .blend_set = wndwc37e_blend_set,
.update = wndwc37e_update,
};
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h
index f29f2d8da142..9ac3dda4b44f 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h
@@ -26,4 +26,6 @@ nvbios_extdev_parse(struct nvkm_bios *, int, struct nvbios_extdev_func *);
int
nvbios_extdev_find(struct nvkm_bios *, enum nvbios_extdev_type,
struct nvbios_extdev_func *);
+
+bool nvbios_extdev_skip_probe(struct nvkm_bios *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
index 7c4f00366e71..3f785f29dfac 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
@@ -3,10 +3,13 @@
#define __NVBIOS_GPIO_H__
enum dcb_gpio_func_name {
DCB_GPIO_PANEL_POWER = 0x01,
+ DCB_GPIO_FAN = 0x09,
DCB_GPIO_TVDAC0 = 0x0c,
+ DCB_GPIO_THERM_EXT_POWER_EVENT = 0x10,
DCB_GPIO_TVDAC1 = 0x2d,
- DCB_GPIO_FAN = 0x09,
DCB_GPIO_FAN_SENSE = 0x3d,
+ DCB_GPIO_POWER_ALERT = 0x4c,
+ DCB_GPIO_EXT_POWER_LOW = 0x79,
DCB_GPIO_LOGO_LED_PWM = 0x84,
DCB_GPIO_UNUSED = 0xff,
DCB_GPIO_VID0 = 0x04,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
index 24fbcccd93eb..4752006880f3 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
@@ -30,6 +30,7 @@ struct nvkm_pmu {
int nvkm_pmu_send(struct nvkm_pmu *, u32 reply[2], u32 process,
u32 message, u32 data0, u32 data1);
void nvkm_pmu_pgob(struct nvkm_pmu *, bool enable);
+bool nvkm_pmu_fan_controlled(struct nvkm_device *);
int gt215_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
int gf100_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 66bf2aff4a3e..d204ea8a5618 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -22,8 +22,6 @@
* SOFTWARE.
*/
-#include <drm/drmP.h>
-
#include "nouveau_drv.h"
#include "nouveau_reg.h"
#include "dispnv04/hw.h"
@@ -935,7 +933,7 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios,
tmdstableptr = ROM16(bios->data[bitentry->offset]);
if (!tmdstableptr) {
- NV_ERROR(drm, "Pointer to TMDS table invalid\n");
+ NV_INFO(drm, "Pointer to TMDS table not found\n");
return -EINVAL;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index e918b437af17..f8015e0318d7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -136,10 +136,16 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
struct drm_device *dev = drm->dev;
struct nouveau_bo *nvbo = nouveau_bo(bo);
- if (unlikely(nvbo->bo.base.filp))
- DRM_ERROR("bo %p still attached to GEM object\n", bo);
WARN_ON(nvbo->pin_refcnt > 0);
nv10_bo_put_tile_region(dev, nvbo->tile, NULL);
+
+ /*
+ * If nouveau_bo_new() allocated this buffer, the GEM object was never
+ * initialized, so don't attempt to release it.
+ */
+ if (bo->base.dev)
+ drm_gem_object_release(&bo->base);
+
kfree(nvbo);
}
@@ -186,8 +192,8 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
}
struct nouveau_bo *
-nouveau_bo_alloc(struct nouveau_cli *cli, u64 size, u32 flags, u32 tile_mode,
- u32 tile_flags)
+nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 flags,
+ u32 tile_mode, u32 tile_flags)
{
struct nouveau_drm *drm = cli->drm;
struct nouveau_bo *nvbo;
@@ -195,8 +201,8 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 size, u32 flags, u32 tile_mode,
struct nvif_vmm *vmm = cli->svm.cli ? &cli->svm.vmm : &cli->vmm.vmm;
int i, pi = -1;
- if (!size) {
- NV_WARN(drm, "skipped size %016llx\n", size);
+ if (!*size) {
+ NV_WARN(drm, "skipped size %016llx\n", *size);
return ERR_PTR(-EINVAL);
}
@@ -266,7 +272,7 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 size, u32 flags, u32 tile_mode,
pi = i;
/* Stop once the buffer is larger than the current page size. */
- if (size >= 1ULL << vmm->page[i].shift)
+ if (*size >= 1ULL << vmm->page[i].shift)
break;
}
@@ -281,6 +287,8 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 size, u32 flags, u32 tile_mode,
}
nvbo->page = vmm->page[pi].shift;
+ nouveau_bo_fixup_align(nvbo, flags, align, size);
+
return nvbo;
}
@@ -294,7 +302,6 @@ nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 flags,
acc_size = ttm_bo_dma_acc_size(nvbo->bo.bdev, size, sizeof(*nvbo));
- nouveau_bo_fixup_align(nvbo, flags, &align, &size);
nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
nouveau_bo_placement_set(nvbo, flags, 0);
@@ -318,7 +325,8 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
struct nouveau_bo *nvbo;
int ret;
- nvbo = nouveau_bo_alloc(cli, size, flags, tile_mode, tile_flags);
+ nvbo = nouveau_bo_alloc(cli, &size, &align, flags, tile_mode,
+ tile_flags);
if (IS_ERR(nvbo))
return PTR_ERR(nvbo);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h
index 62930d834fba..38f9d8350963 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.h
@@ -71,8 +71,8 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo)
extern struct ttm_bo_driver nouveau_bo_driver;
void nouveau_bo_move_init(struct nouveau_drm *);
-struct nouveau_bo *nouveau_bo_alloc(struct nouveau_cli *, u64 size, u32 flags,
- u32 tile_mode, u32 tile_flags);
+struct nouveau_bo *nouveau_bo_alloc(struct nouveau_cli *, u64 *size, int *align,
+ u32 flags, u32 tile_mode, u32 tile_flags);
int nouveau_bo_init(struct nouveau_bo *, u64 size, int align, u32 flags,
struct sg_table *sg, struct dma_resv *robj);
int nouveau_bo_new(struct nouveau_cli *, u64 size, int align, u32 flags,
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 54317bc31e31..3a5db17bc5c7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -29,7 +29,6 @@
#include <linux/pm_runtime.h>
#include <linux/vga_switcheroo.h>
-#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_crtc_helper.h>
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index 366acb928f57..7f63be2ec35d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -27,6 +27,8 @@
#ifndef __NOUVEAU_CRTC_H__
#define __NOUVEAU_CRTC_H__
+#include <drm/drm_crtc.h>
+
#include <nvif/notify.h>
struct nouveau_crtc {
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.h b/drivers/gpu/drm/nouveau/nouveau_debugfs.h
index 9420a6aca138..8909c010e8ea 100644
--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.h
+++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.h
@@ -2,7 +2,7 @@
#ifndef __NOUVEAU_DEBUGFS_H__
#define __NOUVEAU_DEBUGFS_H__
-#include <drm/drmP.h>
+#include <drm/drm_debugfs.h>
#if defined(CONFIG_DEBUG_FS)
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 98afc50162e9..6f038511a03a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -25,12 +25,14 @@
*/
#include <acpi/video.h>
-#include <drm/drmP.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
#include "nouveau_fbcon.h"
#include "nouveau_crtc.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 9185f01e2d9b..6e8e66882e45 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -1,9 +1,13 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NOUVEAU_DISPLAY_H__
#define __NOUVEAU_DISPLAY_H__
+
#include "nouveau_drv.h"
+
#include <nvif/disp.h>
+#include <drm/drm_framebuffer.h>
+
struct nouveau_framebuffer {
struct drm_framebuffer base;
struct nouveau_bo *nvbo;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index 078f65d849ce..3c430a550a51 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -118,7 +118,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
}
if ((++cnt & 0xff) == 0) {
- DRM_UDELAY(1);
+ udelay(1);
if (cnt > 100000)
return -EBUSY;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c
index 1333220787a1..fa1439941596 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dmem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c
@@ -44,8 +44,6 @@
#define DMEM_CHUNK_SIZE (2UL << 20)
#define DMEM_CHUNK_NPAGES (DMEM_CHUNK_SIZE >> PAGE_SHIFT)
-struct nouveau_migrate;
-
enum nouveau_aper {
NOUVEAU_APER_VIRT,
NOUVEAU_APER_VRAM,
@@ -86,21 +84,13 @@ static inline struct nouveau_dmem *page_to_dmem(struct page *page)
return container_of(page->pgmap, struct nouveau_dmem, pagemap);
}
-struct nouveau_dmem_fault {
- struct nouveau_drm *drm;
- struct nouveau_fence *fence;
- dma_addr_t *dma;
- unsigned long npages;
-};
+static unsigned long nouveau_dmem_page_addr(struct page *page)
+{
+ struct nouveau_dmem_chunk *chunk = page->zone_device_data;
+ unsigned long idx = page_to_pfn(page) - chunk->pfn_first;
-struct nouveau_migrate {
- struct vm_area_struct *vma;
- struct nouveau_drm *drm;
- struct nouveau_fence *fence;
- unsigned long npages;
- dma_addr_t *dma;
- unsigned long dma_nr;
-};
+ return (idx << PAGE_SHIFT) + chunk->bo->bo.offset;
+}
static void nouveau_dmem_page_free(struct page *page)
{
@@ -125,165 +115,90 @@ static void nouveau_dmem_page_free(struct page *page)
spin_unlock(&chunk->lock);
}
-static void
-nouveau_dmem_fault_alloc_and_copy(struct vm_area_struct *vma,
- const unsigned long *src_pfns,
- unsigned long *dst_pfns,
- unsigned long start,
- unsigned long end,
- void *private)
+static void nouveau_dmem_fence_done(struct nouveau_fence **fence)
{
- struct nouveau_dmem_fault *fault = private;
- struct nouveau_drm *drm = fault->drm;
- struct device *dev = drm->dev->dev;
- unsigned long addr, i, npages = 0;
- nouveau_migrate_copy_t copy;
- int ret;
-
-
- /* First allocate new memory */
- for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, i++) {
- struct page *dpage, *spage;
-
- dst_pfns[i] = 0;
- spage = migrate_pfn_to_page(src_pfns[i]);
- if (!spage || !(src_pfns[i] & MIGRATE_PFN_MIGRATE))
- continue;
-
- dpage = alloc_page_vma(GFP_HIGHUSER, vma, addr);
- if (!dpage) {
- dst_pfns[i] = MIGRATE_PFN_ERROR;
- continue;
- }
- lock_page(dpage);
-
- dst_pfns[i] = migrate_pfn(page_to_pfn(dpage)) |
- MIGRATE_PFN_LOCKED;
- npages++;
- }
-
- /* Allocate storage for DMA addresses, so we can unmap later. */
- fault->dma = kmalloc(sizeof(*fault->dma) * npages, GFP_KERNEL);
- if (!fault->dma)
- goto error;
-
- /* Copy things over */
- copy = drm->dmem->migrate.copy_func;
- for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, i++) {
- struct nouveau_dmem_chunk *chunk;
- struct page *spage, *dpage;
- u64 src_addr, dst_addr;
-
- dpage = migrate_pfn_to_page(dst_pfns[i]);
- if (!dpage || dst_pfns[i] == MIGRATE_PFN_ERROR)
- continue;
-
- spage = migrate_pfn_to_page(src_pfns[i]);
- if (!spage || !(src_pfns[i] & MIGRATE_PFN_MIGRATE)) {
- dst_pfns[i] = MIGRATE_PFN_ERROR;
- __free_page(dpage);
- continue;
- }
-
- fault->dma[fault->npages] =
- dma_map_page_attrs(dev, dpage, 0, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL,
- DMA_ATTR_SKIP_CPU_SYNC);
- if (dma_mapping_error(dev, fault->dma[fault->npages])) {
- dst_pfns[i] = MIGRATE_PFN_ERROR;
- __free_page(dpage);
- continue;
- }
-
- dst_addr = fault->dma[fault->npages++];
-
- chunk = spage->zone_device_data;
- src_addr = page_to_pfn(spage) - chunk->pfn_first;
- src_addr = (src_addr << PAGE_SHIFT) + chunk->bo->bo.offset;
-
- ret = copy(drm, 1, NOUVEAU_APER_HOST, dst_addr,
- NOUVEAU_APER_VRAM, src_addr);
- if (ret) {
- dst_pfns[i] = MIGRATE_PFN_ERROR;
- __free_page(dpage);
- continue;
- }
+ if (fence) {
+ nouveau_fence_wait(*fence, true, false);
+ nouveau_fence_unref(fence);
+ } else {
+ /*
+ * FIXME wait for channel to be IDLE before calling finalizing
+ * the hmem object.
+ */
}
+}
- nouveau_fence_new(drm->dmem->migrate.chan, false, &fault->fence);
-
- return;
-
-error:
- for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, ++i) {
- struct page *page;
+static vm_fault_t nouveau_dmem_fault_copy_one(struct nouveau_drm *drm,
+ struct vm_fault *vmf, struct migrate_vma *args,
+ dma_addr_t *dma_addr)
+{
+ struct device *dev = drm->dev->dev;
+ struct page *dpage, *spage;
- if (!dst_pfns[i] || dst_pfns[i] == MIGRATE_PFN_ERROR)
- continue;
+ spage = migrate_pfn_to_page(args->src[0]);
+ if (!spage || !(args->src[0] & MIGRATE_PFN_MIGRATE))
+ return 0;
- page = migrate_pfn_to_page(dst_pfns[i]);
- dst_pfns[i] = MIGRATE_PFN_ERROR;
- if (page == NULL)
- continue;
+ dpage = alloc_page_vma(GFP_HIGHUSER, vmf->vma, vmf->address);
+ if (!dpage)
+ return VM_FAULT_SIGBUS;
+ lock_page(dpage);
- __free_page(page);
- }
-}
+ *dma_addr = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, *dma_addr))
+ goto error_free_page;
-void nouveau_dmem_fault_finalize_and_map(struct vm_area_struct *vma,
- const unsigned long *src_pfns,
- const unsigned long *dst_pfns,
- unsigned long start,
- unsigned long end,
- void *private)
-{
- struct nouveau_dmem_fault *fault = private;
- struct nouveau_drm *drm = fault->drm;
+ if (drm->dmem->migrate.copy_func(drm, 1, NOUVEAU_APER_HOST, *dma_addr,
+ NOUVEAU_APER_VRAM, nouveau_dmem_page_addr(spage)))
+ goto error_dma_unmap;
- if (fault->fence) {
- nouveau_fence_wait(fault->fence, true, false);
- nouveau_fence_unref(&fault->fence);
- } else {
- /*
- * FIXME wait for channel to be IDLE before calling finalizing
- * the hmem object below (nouveau_migrate_hmem_fini()).
- */
- }
+ args->dst[0] = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED;
+ return 0;
- while (fault->npages--) {
- dma_unmap_page(drm->dev->dev, fault->dma[fault->npages],
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
- }
- kfree(fault->dma);
+error_dma_unmap:
+ dma_unmap_page(dev, *dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
+error_free_page:
+ __free_page(dpage);
+ return VM_FAULT_SIGBUS;
}
-static const struct migrate_vma_ops nouveau_dmem_fault_migrate_ops = {
- .alloc_and_copy = nouveau_dmem_fault_alloc_and_copy,
- .finalize_and_map = nouveau_dmem_fault_finalize_and_map,
-};
-
static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf)
{
struct nouveau_dmem *dmem = page_to_dmem(vmf->page);
- unsigned long src[1] = {0}, dst[1] = {0};
- struct nouveau_dmem_fault fault = { .drm = dmem->drm };
- int ret;
+ struct nouveau_drm *drm = dmem->drm;
+ struct nouveau_fence *fence;
+ unsigned long src = 0, dst = 0;
+ dma_addr_t dma_addr = 0;
+ vm_fault_t ret;
+ struct migrate_vma args = {
+ .vma = vmf->vma,
+ .start = vmf->address,
+ .end = vmf->address + PAGE_SIZE,
+ .src = &src,
+ .dst = &dst,
+ };
/*
* FIXME what we really want is to find some heuristic to migrate more
* than just one page on CPU fault. When such fault happens it is very
* likely that more surrounding page will CPU fault too.
*/
- ret = migrate_vma(&nouveau_dmem_fault_migrate_ops, vmf->vma,
- vmf->address, vmf->address + PAGE_SIZE,
- src, dst, &fault);
- if (ret)
+ if (migrate_vma_setup(&args) < 0)
return VM_FAULT_SIGBUS;
+ if (!args.cpages)
+ return 0;
- if (dst[0] == MIGRATE_PFN_ERROR)
- return VM_FAULT_SIGBUS;
+ ret = nouveau_dmem_fault_copy_one(drm, vmf, &args, &dma_addr);
+ if (ret || dst == 0)
+ goto done;
- return 0;
+ nouveau_fence_new(dmem->migrate.chan, false, &fence);
+ migrate_vma_pages(&args);
+ nouveau_dmem_fence_done(&fence);
+ dma_unmap_page(drm->dev->dev, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
+done:
+ migrate_vma_finalize(&args);
+ return ret;
}
static const struct dev_pagemap_ops nouveau_dmem_pagemap_ops = {
@@ -642,188 +557,115 @@ out_free:
drm->dmem = NULL;
}
-static void
-nouveau_dmem_migrate_alloc_and_copy(struct vm_area_struct *vma,
- const unsigned long *src_pfns,
- unsigned long *dst_pfns,
- unsigned long start,
- unsigned long end,
- void *private)
+static unsigned long nouveau_dmem_migrate_copy_one(struct nouveau_drm *drm,
+ unsigned long src, dma_addr_t *dma_addr)
{
- struct nouveau_migrate *migrate = private;
- struct nouveau_drm *drm = migrate->drm;
struct device *dev = drm->dev->dev;
- unsigned long addr, i, npages = 0;
- nouveau_migrate_copy_t copy;
- int ret;
-
- /* First allocate new memory */
- for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, i++) {
- struct page *dpage, *spage;
-
- dst_pfns[i] = 0;
- spage = migrate_pfn_to_page(src_pfns[i]);
- if (!spage || !(src_pfns[i] & MIGRATE_PFN_MIGRATE))
- continue;
-
- dpage = nouveau_dmem_page_alloc_locked(drm);
- if (!dpage)
- continue;
-
- dst_pfns[i] = migrate_pfn(page_to_pfn(dpage)) |
- MIGRATE_PFN_LOCKED |
- MIGRATE_PFN_DEVICE;
- npages++;
- }
-
- if (!npages)
- return;
-
- /* Allocate storage for DMA addresses, so we can unmap later. */
- migrate->dma = kmalloc(sizeof(*migrate->dma) * npages, GFP_KERNEL);
- if (!migrate->dma)
- goto error;
-
- /* Copy things over */
- copy = drm->dmem->migrate.copy_func;
- for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, i++) {
- struct nouveau_dmem_chunk *chunk;
- struct page *spage, *dpage;
- u64 src_addr, dst_addr;
-
- dpage = migrate_pfn_to_page(dst_pfns[i]);
- if (!dpage || dst_pfns[i] == MIGRATE_PFN_ERROR)
- continue;
-
- chunk = dpage->zone_device_data;
- dst_addr = page_to_pfn(dpage) - chunk->pfn_first;
- dst_addr = (dst_addr << PAGE_SHIFT) + chunk->bo->bo.offset;
-
- spage = migrate_pfn_to_page(src_pfns[i]);
- if (!spage || !(src_pfns[i] & MIGRATE_PFN_MIGRATE)) {
- nouveau_dmem_page_free_locked(drm, dpage);
- dst_pfns[i] = 0;
- continue;
- }
-
- migrate->dma[migrate->dma_nr] =
- dma_map_page_attrs(dev, spage, 0, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL,
- DMA_ATTR_SKIP_CPU_SYNC);
- if (dma_mapping_error(dev, migrate->dma[migrate->dma_nr])) {
- nouveau_dmem_page_free_locked(drm, dpage);
- dst_pfns[i] = 0;
- continue;
- }
-
- src_addr = migrate->dma[migrate->dma_nr++];
+ struct page *dpage, *spage;
- ret = copy(drm, 1, NOUVEAU_APER_VRAM, dst_addr,
- NOUVEAU_APER_HOST, src_addr);
- if (ret) {
- nouveau_dmem_page_free_locked(drm, dpage);
- dst_pfns[i] = 0;
- continue;
- }
- }
-
- nouveau_fence_new(drm->dmem->migrate.chan, false, &migrate->fence);
+ spage = migrate_pfn_to_page(src);
+ if (!spage || !(src & MIGRATE_PFN_MIGRATE))
+ goto out;
- return;
+ dpage = nouveau_dmem_page_alloc_locked(drm);
+ if (!dpage)
+ return 0;
-error:
- for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, ++i) {
- struct page *page;
+ *dma_addr = dma_map_page(dev, spage, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, *dma_addr))
+ goto out_free_page;
- if (!dst_pfns[i] || dst_pfns[i] == MIGRATE_PFN_ERROR)
- continue;
+ if (drm->dmem->migrate.copy_func(drm, 1, NOUVEAU_APER_VRAM,
+ nouveau_dmem_page_addr(dpage), NOUVEAU_APER_HOST,
+ *dma_addr))
+ goto out_dma_unmap;
- page = migrate_pfn_to_page(dst_pfns[i]);
- dst_pfns[i] = MIGRATE_PFN_ERROR;
- if (page == NULL)
- continue;
+ return migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED;
- __free_page(page);
- }
+out_dma_unmap:
+ dma_unmap_page(dev, *dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
+out_free_page:
+ nouveau_dmem_page_free_locked(drm, dpage);
+out:
+ return 0;
}
-void nouveau_dmem_migrate_finalize_and_map(struct vm_area_struct *vma,
- const unsigned long *src_pfns,
- const unsigned long *dst_pfns,
- unsigned long start,
- unsigned long end,
- void *private)
+static void nouveau_dmem_migrate_chunk(struct nouveau_drm *drm,
+ struct migrate_vma *args, dma_addr_t *dma_addrs)
{
- struct nouveau_migrate *migrate = private;
- struct nouveau_drm *drm = migrate->drm;
-
- if (migrate->fence) {
- nouveau_fence_wait(migrate->fence, true, false);
- nouveau_fence_unref(&migrate->fence);
- } else {
- /*
- * FIXME wait for channel to be IDLE before finalizing
- * the hmem object below (nouveau_migrate_hmem_fini()) ?
- */
+ struct nouveau_fence *fence;
+ unsigned long addr = args->start, nr_dma = 0, i;
+
+ for (i = 0; addr < args->end; i++) {
+ args->dst[i] = nouveau_dmem_migrate_copy_one(drm, args->src[i],
+ dma_addrs + nr_dma);
+ if (args->dst[i])
+ nr_dma++;
+ addr += PAGE_SIZE;
}
- while (migrate->dma_nr--) {
- dma_unmap_page(drm->dev->dev, migrate->dma[migrate->dma_nr],
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
- }
- kfree(migrate->dma);
+ nouveau_fence_new(drm->dmem->migrate.chan, false, &fence);
+ migrate_vma_pages(args);
+ nouveau_dmem_fence_done(&fence);
+ while (nr_dma--) {
+ dma_unmap_page(drm->dev->dev, dma_addrs[nr_dma], PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ }
/*
- * FIXME optimization: update GPU page table to point to newly
- * migrated memory.
+ * FIXME optimization: update GPU page table to point to newly migrated
+ * memory.
*/
+ migrate_vma_finalize(args);
}
-static const struct migrate_vma_ops nouveau_dmem_migrate_ops = {
- .alloc_and_copy = nouveau_dmem_migrate_alloc_and_copy,
- .finalize_and_map = nouveau_dmem_migrate_finalize_and_map,
-};
-
int
nouveau_dmem_migrate_vma(struct nouveau_drm *drm,
struct vm_area_struct *vma,
unsigned long start,
unsigned long end)
{
- unsigned long *src_pfns, *dst_pfns, npages;
- struct nouveau_migrate migrate = {0};
- unsigned long i, c, max;
- int ret = 0;
-
- npages = (end - start) >> PAGE_SHIFT;
- max = min(SG_MAX_SINGLE_ALLOC, npages);
- src_pfns = kzalloc(sizeof(long) * max, GFP_KERNEL);
- if (src_pfns == NULL)
- return -ENOMEM;
- dst_pfns = kzalloc(sizeof(long) * max, GFP_KERNEL);
- if (dst_pfns == NULL) {
- kfree(src_pfns);
- return -ENOMEM;
- }
+ unsigned long npages = (end - start) >> PAGE_SHIFT;
+ unsigned long max = min(SG_MAX_SINGLE_ALLOC, npages);
+ dma_addr_t *dma_addrs;
+ struct migrate_vma args = {
+ .vma = vma,
+ .start = start,
+ };
+ unsigned long c, i;
+ int ret = -ENOMEM;
+
+ args.src = kcalloc(max, sizeof(args.src), GFP_KERNEL);
+ if (!args.src)
+ goto out;
+ args.dst = kcalloc(max, sizeof(args.dst), GFP_KERNEL);
+ if (!args.dst)
+ goto out_free_src;
- migrate.drm = drm;
- migrate.vma = vma;
- migrate.npages = npages;
- for (i = 0; i < npages; i += c) {
- unsigned long next;
+ dma_addrs = kmalloc_array(max, sizeof(*dma_addrs), GFP_KERNEL);
+ if (!dma_addrs)
+ goto out_free_dst;
+ for (i = 0; i < npages; i += c) {
c = min(SG_MAX_SINGLE_ALLOC, npages);
- next = start + (c << PAGE_SHIFT);
- ret = migrate_vma(&nouveau_dmem_migrate_ops, vma, start,
- next, src_pfns, dst_pfns, &migrate);
+ args.end = start + (c << PAGE_SHIFT);
+ ret = migrate_vma_setup(&args);
if (ret)
- goto out;
- start = next;
+ goto out_free_dma;
+
+ if (args.cpages)
+ nouveau_dmem_migrate_chunk(drm, &args, dma_addrs);
+ args.start = args.end;
}
+ ret = 0;
+out_free_dma:
+ kfree(dma_addrs);
+out_free_dst:
+ kfree(args.dst);
+out_free_src:
+ kfree(args.src);
out:
- kfree(dst_pfns);
- kfree(src_pfns);
return ret;
}
@@ -841,11 +683,10 @@ nouveau_dmem_convert_pfn(struct nouveau_drm *drm,
npages = (range->end - range->start) >> PAGE_SHIFT;
for (i = 0; i < npages; ++i) {
- struct nouveau_dmem_chunk *chunk;
struct page *page;
uint64_t addr;
- page = hmm_pfn_to_page(range, range->pfns[i]);
+ page = hmm_device_entry_to_page(range, range->pfns[i]);
if (page == NULL)
continue;
@@ -859,10 +700,7 @@ nouveau_dmem_convert_pfn(struct nouveau_drm *drm,
continue;
}
- chunk = page->zone_device_data;
- addr = page_to_pfn(page) - chunk->pfn_first;
- addr = (addr + chunk->bo->bo.mem.start) << PAGE_SHIFT;
-
+ addr = nouveau_dmem_page_addr(page);
range->pfns[i] &= ((1UL << range->pfn_shift) - 1);
range->pfns[i] |= (addr >> PAGE_SHIFT) << range->pfn_shift;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.h b/drivers/gpu/drm/nouveau/nouveau_dmem.h
index 9d97d756fb7d..92394be5d649 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dmem.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dmem.h
@@ -45,16 +45,5 @@ static inline void nouveau_dmem_init(struct nouveau_drm *drm) {}
static inline void nouveau_dmem_fini(struct nouveau_drm *drm) {}
static inline void nouveau_dmem_suspend(struct nouveau_drm *drm) {}
static inline void nouveau_dmem_resume(struct nouveau_drm *drm) {}
-
-static inline int nouveau_dmem_migrate_vma(struct nouveau_drm *drm,
- struct vm_area_struct *vma,
- unsigned long start,
- unsigned long end)
-{
- return 0;
-}
-
-static inline void nouveau_dmem_convert_pfn(struct nouveau_drm *drm,
- struct hmm_range *range) {}
#endif /* IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM) */
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 0d052e1660f8..2674f1587457 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -22,7 +22,6 @@
* Authors: Ben Skeggs
*/
-#include <drm/drmP.h>
#include <drm/drm_dp_helper.h>
#include "nouveau_drv.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 7e045580a3a4..2cd83849600f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -28,9 +28,11 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/vga_switcheroo.h>
+#include <linux/mmu_notifier.h>
-#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_vblank.h>
#include <core/gpuobj.h>
#include <core/option.h>
@@ -1289,6 +1291,8 @@ nouveau_drm_exit(void)
#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
platform_driver_unregister(&nouveau_platform_driver);
#endif
+ if (IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM))
+ mmu_notifier_synchronize();
}
module_init(nouveau_drm_init);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index aae035816383..70f34cacc552 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -46,7 +46,10 @@
#include <nvif/mmu.h>
#include <nvif/vmm.h>
-#include <drm/drmP.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
#include <drm/ttm/ttm_bo_api.h>
#include <drm/ttm/ttm_bo_driver.h>
@@ -127,7 +130,6 @@ nouveau_cli(struct drm_file *fpriv)
}
#include <nvif/object.h>
-#include <nvif/device.h>
struct nouveau_drm {
struct nouveau_cli master;
@@ -204,9 +206,6 @@ struct nouveau_drm {
/* led management */
struct nouveau_led *led;
- /* display power reference */
- bool have_disp_power_ref;
-
struct dev_pm_domain vga_pm_domain;
struct nouveau_svm *svm;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 73cc3217068a..f439f0a5b43a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -37,10 +37,10 @@
#include <linux/vga_switcheroo.h>
#include <linux/console.h>
-#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_atomic.h>
#include "nouveau_drv.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 8df390078c85..9118df035b28 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -24,10 +24,9 @@
*
*/
-#include <drm/drmP.h>
-
#include <linux/ktime.h>
#include <linux/hrtimer.h>
+#include <linux/sched/signal.h>
#include <trace/events/dma_fence.h>
#include <nvif/cl826e.h>
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index c2bfc0591909..1324c19f4e5c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -51,10 +51,6 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
if (gem->import_attach)
drm_prime_gem_destroy(gem, nvbo->bo.sg);
- drm_gem_object_release(gem);
-
- /* reset filp so nouveau_bo_del_ttm() can test for it */
- gem->filp = NULL;
ttm_bo_put(&nvbo->bo);
pm_runtime_mark_last_busy(dev);
@@ -188,7 +184,8 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain,
if (domain & NOUVEAU_GEM_DOMAIN_COHERENT)
flags |= TTM_PL_FLAG_UNCACHED;
- nvbo = nouveau_bo_alloc(cli, size, flags, tile_mode, tile_flags);
+ nvbo = nouveau_bo_alloc(cli, &size, &align, flags, tile_mode,
+ tile_flags);
if (IS_ERR(nvbo))
return PTR_ERR(nvbo);
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h
index 40ba0f1ba5aa..978e07591990 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.h
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.h
@@ -2,8 +2,6 @@
#ifndef __NOUVEAU_GEM_H__
#define __NOUVEAU_GEM_H__
-#include <drm/drmP.h>
-
#include "nouveau_drv.h"
#include "nouveau_bo.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
index 6af2d299c3f9..d445c6f3fece 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
@@ -29,8 +29,6 @@
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-#include <drm/drmP.h>
-
#include "nouveau_drv.h"
#include "nouveau_hwmon.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_ioc32.c b/drivers/gpu/drm/nouveau/nouveau_ioc32.c
index 462679a8fec5..adf01ca9e035 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ioc32.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ioc32.c
@@ -33,7 +33,8 @@
#include <linux/compat.h>
-#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_ioctl.h>
#include "nouveau_ioctl.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c
index 0247903f0c5c..bae6a3eccee0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_prime.c
+++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
@@ -22,7 +22,6 @@
* Authors: Dave Airlie
*/
-#include <drm/drmP.h>
#include <linux/dma-buf.h>
#include "nouveau_drv.h"
@@ -61,19 +60,22 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
struct sg_table *sg)
{
struct nouveau_drm *drm = nouveau_drm(dev);
+ struct drm_gem_object *obj;
struct nouveau_bo *nvbo;
struct dma_resv *robj = attach->dmabuf->resv;
- size_t size = attach->dmabuf->size;
+ u64 size = attach->dmabuf->size;
u32 flags = 0;
+ int align = 0;
int ret;
flags = TTM_PL_FLAG_TT;
dma_resv_lock(robj, NULL);
- nvbo = nouveau_bo_alloc(&drm->client, size, flags, 0, 0);
- dma_resv_unlock(robj);
- if (IS_ERR(nvbo))
- return ERR_CAST(nvbo);
+ nvbo = nouveau_bo_alloc(&drm->client, &size, &align, flags, 0, 0);
+ if (IS_ERR(nvbo)) {
+ obj = ERR_CAST(nvbo);
+ goto unlock;
+ }
nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_GART;
@@ -82,16 +84,22 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
ret = drm_gem_object_init(dev, &nvbo->bo.base, size);
if (ret) {
nouveau_bo_ref(NULL, &nvbo);
- return ERR_PTR(-ENOMEM);
+ obj = ERR_PTR(-ENOMEM);
+ goto unlock;
}
- ret = nouveau_bo_init(nvbo, size, 0, flags, sg, robj);
+ ret = nouveau_bo_init(nvbo, size, align, flags, sg, robj);
if (ret) {
nouveau_bo_ref(NULL, &nvbo);
- return ERR_PTR(ret);
+ obj = ERR_PTR(ret);
+ goto unlock;
}
- return &nvbo->bo.base;
+ obj = &nvbo->bo.base;
+
+unlock:
+ dma_resv_unlock(robj);
+ return obj;
}
int nouveau_gem_prime_pin(struct drm_gem_object *obj)
diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
index 8c92374afcf2..668d4bd0c118 100644
--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
@@ -252,13 +252,13 @@ nouveau_svmm_invalidate(struct nouveau_svmm *svmm, u64 start, u64 limit)
static int
nouveau_svmm_sync_cpu_device_pagetables(struct hmm_mirror *mirror,
- const struct hmm_update *update)
+ const struct mmu_notifier_range *update)
{
struct nouveau_svmm *svmm = container_of(mirror, typeof(*svmm), mirror);
unsigned long start = update->start;
unsigned long limit = update->end;
- if (!update->blockable)
+ if (!mmu_notifier_range_blockable(update))
return -EAGAIN;
SVMM_DBG(svmm, "invalidate %016lx-%016lx", start, limit);
@@ -475,6 +475,45 @@ nouveau_svm_fault_cache(struct nouveau_svm *svm,
fault->inst, fault->addr, fault->access);
}
+static inline bool
+nouveau_range_done(struct hmm_range *range)
+{
+ bool ret = hmm_range_valid(range);
+
+ hmm_range_unregister(range);
+ return ret;
+}
+
+static int
+nouveau_range_fault(struct nouveau_svmm *svmm, struct hmm_range *range)
+{
+ long ret;
+
+ range->default_flags = 0;
+ range->pfn_flags_mask = -1UL;
+
+ ret = hmm_range_register(range, &svmm->mirror);
+ if (ret) {
+ up_read(&svmm->mm->mmap_sem);
+ return (int)ret;
+ }
+
+ if (!hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT)) {
+ up_read(&svmm->mm->mmap_sem);
+ return -EBUSY;
+ }
+
+ ret = hmm_range_fault(range, 0);
+ if (ret <= 0) {
+ if (ret == 0)
+ ret = -EBUSY;
+ up_read(&svmm->mm->mmap_sem);
+ hmm_range_unregister(range);
+ return ret;
+ }
+ return 0;
+}
+
static int
nouveau_svm_fault(struct nvif_notify *notify)
{
@@ -641,7 +680,6 @@ nouveau_svm_fault(struct nvif_notify *notify)
args.i.p.addr + args.i.p.size, fn - fi);
/* Have HMM fault pages within the fault window to the GPU. */
- range.vma = vma;
range.start = args.i.p.addr;
range.end = args.i.p.addr + args.i.p.size;
range.pfns = args.phys;
@@ -649,10 +687,10 @@ nouveau_svm_fault(struct nvif_notify *notify)
range.values = nouveau_svm_pfn_values;
range.pfn_shift = NVIF_VMM_PFNMAP_V0_ADDR_SHIFT;
again:
- ret = hmm_vma_fault(&svmm->mirror, &range, true);
+ ret = nouveau_range_fault(svmm, &range);
if (ret == 0) {
mutex_lock(&svmm->mutex);
- if (!hmm_vma_range_done(&range)) {
+ if (!nouveau_range_done(&range)) {
mutex_unlock(&svmm->mutex);
goto again;
}
@@ -666,8 +704,8 @@ again:
NULL);
svmm->vmm->vmm.object.client->super = false;
mutex_unlock(&svmm->mutex);
+ up_read(&svmm->mm->mmap_sem);
}
- up_read(&svmm->mm->mmap_sem);
/* Cancel any faults in the window whose pages didn't manage
* to keep their valid bit, or stay writeable when required.
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 8f4b12a8092c..d865d8aeac3c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -2,7 +2,6 @@
#include <linux/vgaarb.h>
#include <linux/vga_switcheroo.h>
-#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
diff --git a/drivers/gpu/drm/nouveau/nvif/mmu.c b/drivers/gpu/drm/nouveau/nvif/mmu.c
index ae08a1ca8044..5641bda2046d 100644
--- a/drivers/gpu/drm/nouveau/nvif/mmu.c
+++ b/drivers/gpu/drm/nouveau/nvif/mmu.c
@@ -110,7 +110,7 @@ nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu)
if (mmu->kind_nr) {
struct nvif_mmu_kind_v0 *kind;
- u32 argc = sizeof(*kind) + sizeof(*kind->data) * mmu->kind_nr;
+ size_t argc = struct_size(kind, data, mmu->kind_nr);
if (ret = -ENOMEM, !(kind = kmalloc(argc, GFP_KERNEL)))
goto done;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index 10a2e7039a75..5a39e51d42d7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -28,6 +28,7 @@
#include <core/enum.h>
#include <core/gpuobj.h>
#include <subdev/bar.h>
+#include <subdev/fault.h>
#include <engine/sw.h>
#include <nvif/class.h>
@@ -194,68 +195,6 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
}
static const struct nvkm_enum
-gf100_fifo_sched_reason[] = {
- { 0x0a, "CTXSW_TIMEOUT" },
- {}
-};
-
-static void
-gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo)
-{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_engine *engine;
- struct gf100_fifo_chan *chan;
- unsigned long flags;
- u32 engn;
-
- spin_lock_irqsave(&fifo->base.lock, flags);
- for (engn = 0; engn < 6; engn++) {
- u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04));
- u32 busy = (stat & 0x80000000);
- u32 save = (stat & 0x00100000); /* maybe? */
- u32 unk0 = (stat & 0x00040000);
- u32 unk1 = (stat & 0x00001000);
- u32 chid = (stat & 0x0000007f);
- (void)save;
-
- if (busy && unk0 && unk1) {
- list_for_each_entry(chan, &fifo->chan, head) {
- if (chan->base.chid == chid) {
- engine = gf100_fifo_engine(fifo, engn);
- if (!engine)
- break;
- gf100_fifo_recover(fifo, engine, chan);
- break;
- }
- }
- }
- }
- spin_unlock_irqrestore(&fifo->base.lock, flags);
-}
-
-static void
-gf100_fifo_intr_sched(struct gf100_fifo *fifo)
-{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 intr = nvkm_rd32(device, 0x00254c);
- u32 code = intr & 0x000000ff;
- const struct nvkm_enum *en;
-
- en = nvkm_enum_find(gf100_fifo_sched_reason, code);
-
- nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : "");
-
- switch (code) {
- case 0x0a:
- gf100_fifo_intr_sched_ctxsw(fifo);
- break;
- default:
- break;
- }
-}
-
-static const struct nvkm_enum
gf100_fifo_fault_engine[] = {
{ 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR },
{ 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB },
@@ -315,32 +254,24 @@ gf100_fifo_fault_gpcclient[] = {
};
static void
-gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
+gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
{
+ struct gf100_fifo *fifo = gf100_fifo(base);
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
- u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10));
- u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10));
- u32 stat = nvkm_rd32(device, 0x00280c + (unit * 0x10));
- u32 gpc = (stat & 0x1f000000) >> 24;
- u32 client = (stat & 0x00001f00) >> 8;
- u32 write = (stat & 0x00000080);
- u32 hub = (stat & 0x00000040);
- u32 reason = (stat & 0x0000000f);
const struct nvkm_enum *er, *eu, *ec;
struct nvkm_engine *engine = NULL;
struct nvkm_fifo_chan *chan;
unsigned long flags;
char gpcid[8] = "";
- er = nvkm_enum_find(gf100_fifo_fault_reason, reason);
- eu = nvkm_enum_find(gf100_fifo_fault_engine, unit);
- if (hub) {
- ec = nvkm_enum_find(gf100_fifo_fault_hubclient, client);
+ er = nvkm_enum_find(gf100_fifo_fault_reason, info->reason);
+ eu = nvkm_enum_find(gf100_fifo_fault_engine, info->engine);
+ if (info->hub) {
+ ec = nvkm_enum_find(gf100_fifo_fault_hubclient, info->client);
} else {
- ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, client);
- snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc);
+ ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, info->client);
+ snprintf(gpcid, sizeof(gpcid), "GPC%d/", info->gpc);
}
if (eu && eu->data2) {
@@ -360,22 +291,108 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
}
}
- chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags);
+ chan = nvkm_fifo_chan_inst(&fifo->base, info->inst, &flags);
nvkm_error(subdev,
"%s fault at %010llx engine %02x [%s] client %02x [%s%s] "
"reason %02x [%s] on channel %d [%010llx %s]\n",
- write ? "write" : "read", (u64)vahi << 32 | valo,
- unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "",
- reason, er ? er->name : "", chan ? chan->chid : -1,
- (u64)inst << 12,
- chan ? chan->object.client->name : "unknown");
+ info->access ? "write" : "read", info->addr,
+ info->engine, eu ? eu->name : "",
+ info->client, gpcid, ec ? ec->name : "",
+ info->reason, er ? er->name : "", chan ? chan->chid : -1,
+ info->inst, chan ? chan->object.client->name : "unknown");
if (engine && chan)
gf100_fifo_recover(fifo, engine, (void *)chan);
nvkm_fifo_chan_put(&fifo->base, flags, &chan);
}
+static const struct nvkm_enum
+gf100_fifo_sched_reason[] = {
+ { 0x0a, "CTXSW_TIMEOUT" },
+ {}
+};
+
+static void
+gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_engine *engine;
+ struct gf100_fifo_chan *chan;
+ unsigned long flags;
+ u32 engn;
+
+ spin_lock_irqsave(&fifo->base.lock, flags);
+ for (engn = 0; engn < 6; engn++) {
+ u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04));
+ u32 busy = (stat & 0x80000000);
+ u32 save = (stat & 0x00100000); /* maybe? */
+ u32 unk0 = (stat & 0x00040000);
+ u32 unk1 = (stat & 0x00001000);
+ u32 chid = (stat & 0x0000007f);
+ (void)save;
+
+ if (busy && unk0 && unk1) {
+ list_for_each_entry(chan, &fifo->chan, head) {
+ if (chan->base.chid == chid) {
+ engine = gf100_fifo_engine(fifo, engn);
+ if (!engine)
+ break;
+ gf100_fifo_recover(fifo, engine, chan);
+ break;
+ }
+ }
+ }
+ }
+ spin_unlock_irqrestore(&fifo->base.lock, flags);
+}
+
+static void
+gf100_fifo_intr_sched(struct gf100_fifo *fifo)
+{
+ struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 intr = nvkm_rd32(device, 0x00254c);
+ u32 code = intr & 0x000000ff;
+ const struct nvkm_enum *en;
+
+ en = nvkm_enum_find(gf100_fifo_sched_reason, code);
+
+ nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : "");
+
+ switch (code) {
+ case 0x0a:
+ gf100_fifo_intr_sched_ctxsw(fifo);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+gf100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
+ u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10));
+ u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10));
+ u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10));
+ struct nvkm_fault_data info;
+
+ info.inst = (u64)inst << 12;
+ info.addr = ((u64)vahi << 32) | valo;
+ info.time = 0;
+ info.engine = unit;
+ info.valid = 1;
+ info.gpc = (type & 0x1f000000) >> 24;
+ info.client = (type & 0x00001f00) >> 8;
+ info.access = (type & 0x00000080) >> 7;
+ info.hub = (type & 0x00000040) >> 6;
+ info.reason = (type & 0x0000000f);
+
+ nvkm_fifo_fault(fifo, &info);
+}
+
static const struct nvkm_bitfield
gf100_fifo_pbdma_intr[] = {
/* { 0x00008000, "" } seen with null ib push */
@@ -518,7 +535,7 @@ gf100_fifo_intr(struct nvkm_fifo *base)
u32 mask = nvkm_rd32(device, 0x00259c);
while (mask) {
u32 unit = __ffs(mask);
- gf100_fifo_intr_fault(fifo, unit);
+ gf100_fifo_intr_fault(&fifo->base, unit);
nvkm_wr32(device, 0x00259c, (1 << unit));
mask &= ~(1 << unit);
}
@@ -655,6 +672,7 @@ gf100_fifo = {
.init = gf100_fifo_init,
.fini = gf100_fifo_fini,
.intr = gf100_fifo_intr,
+ .fault = gf100_fifo_fault,
.uevent_init = gf100_fifo_uevent_init,
.uevent_fini = gf100_fifo_uevent_fini,
.chan = {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index 1053fe796466..5d4b695cab8e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -646,31 +646,6 @@ gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo)
nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat);
}
-static void
-gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
-{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
- u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10));
- u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10));
- u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10));
- struct nvkm_fault_data info;
-
- info.inst = (u64)inst << 12;
- info.addr = ((u64)vahi << 32) | valo;
- info.time = 0;
- info.engine = unit;
- info.valid = 1;
- info.gpc = (type & 0x1f000000) >> 24;
- info.client = (type & 0x00001f00) >> 8;
- info.access = (type & 0x00000080) >> 7;
- info.hub = (type & 0x00000040) >> 6;
- info.reason = (type & 0x000000ff);
-
- nvkm_fifo_fault(&fifo->base, &info);
-}
-
static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = {
{ 0x00000001, "MEMREQ" },
{ 0x00000002, "MEMACK_TIMEOUT" },
@@ -849,7 +824,7 @@ gk104_fifo_intr(struct nvkm_fifo *base)
u32 mask = nvkm_rd32(device, 0x00259c);
while (mask) {
u32 unit = __ffs(mask);
- gk104_fifo_intr_fault(fifo, unit);
+ fifo->func->intr.fault(&fifo->base, unit);
nvkm_wr32(device, 0x00259c, (1 << unit));
mask &= ~(1 << unit);
}
@@ -1204,6 +1179,7 @@ gk104_fifo_fault_gpcclient[] = {
static const struct gk104_fifo_func
gk104_fifo = {
+ .intr.fault = gf100_fifo_intr_fault,
.pbdma = &gk104_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gk104_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
index c33f4593cbc6..6407a4a174cf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
@@ -45,6 +45,10 @@ struct gk104_fifo {
};
struct gk104_fifo_func {
+ struct {
+ void (*fault)(struct nvkm_fifo *, int unit);
+ } intr;
+
const struct gk104_fifo_pbdma_func {
int (*nr)(struct gk104_fifo *);
void (*init)(struct gk104_fifo *);
@@ -110,12 +114,14 @@ void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *,
extern const struct gk104_fifo_pbdma_func gk208_fifo_pbdma;
void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *);
+void gm107_fifo_intr_fault(struct nvkm_fifo *, int);
extern const struct nvkm_enum gm107_fifo_fault_engine[];
extern const struct gk104_fifo_runlist_func gm107_fifo_runlist;
extern const struct gk104_fifo_pbdma_func gm200_fifo_pbdma;
int gm200_fifo_pbdma_nr(struct gk104_fifo *);
+void gp100_fifo_intr_fault(struct nvkm_fifo *, int);
extern const struct nvkm_enum gp100_fifo_fault_engine[];
extern const struct nvkm_enum gv100_fifo_fault_access[];
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
index 8adfa6b182cb..f820969e4405 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
@@ -48,6 +48,7 @@ gk110_fifo_runlist = {
static const struct gk104_fifo_func
gk110_fifo = {
+ .intr.fault = gf100_fifo_intr_fault,
.pbdma = &gk104_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gk104_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
index 9553fb4af601..2f54787b5fd0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
@@ -45,6 +45,7 @@ gk208_fifo_pbdma = {
static const struct gk104_fifo_func
gk208_fifo = {
+ .intr.fault = gf100_fifo_intr_fault,
.pbdma = &gk208_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gk104_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
index a4c6ac3cd6c7..a814c4e0ed3e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
@@ -26,6 +26,7 @@
static const struct gk104_fifo_func
gk20a_fifo = {
+ .intr.fault = gf100_fifo_intr_fault,
.pbdma = &gk208_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gk104_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
index acf230764cb0..c2a2e4572f6c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
@@ -25,6 +25,7 @@
#include "changk104.h"
#include <core/gpuobj.h>
+#include <subdev/fault.h>
#include <nvif/class.h>
@@ -67,8 +68,33 @@ gm107_fifo_fault_engine[] = {
{}
};
+void
+gm107_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
+ u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10));
+ u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10));
+ u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10));
+ struct nvkm_fault_data info;
+
+ info.inst = (u64)inst << 12;
+ info.addr = ((u64)vahi << 32) | valo;
+ info.time = 0;
+ info.engine = unit;
+ info.valid = 1;
+ info.gpc = (type & 0x1f000000) >> 24;
+ info.client = (type & 0x00003f00) >> 8;
+ info.access = (type & 0x00000080) >> 7;
+ info.hub = (type & 0x00000040) >> 6;
+ info.reason = (type & 0x0000000f);
+
+ nvkm_fifo_fault(fifo, &info);
+}
+
static const struct gk104_fifo_func
gm107_fifo = {
+ .intr.fault = gm107_fifo_intr_fault,
.pbdma = &gk208_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gm107_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
index b96c1c5d6577..b8cfe3b28c4f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
@@ -42,6 +42,7 @@ gm200_fifo_pbdma = {
static const struct gk104_fifo_func
gm200_fifo = {
+ .intr.fault = gm107_fifo_intr_fault,
.pbdma = &gm200_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gm107_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c
index a49539b9e4ec..70b4feebc1fa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c
@@ -26,6 +26,7 @@
static const struct gk104_fifo_func
gm20b_fifo = {
+ .intr.fault = gm107_fifo_intr_fault,
.pbdma = &gm200_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gm107_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
index 54377e0f6a88..2c7a0176b3c8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
@@ -24,6 +24,8 @@
#include "gk104.h"
#include "changk104.h"
+#include <subdev/fault.h>
+
#include <nvif/class.h>
const struct nvkm_enum
@@ -50,8 +52,33 @@ gp100_fifo_fault_engine[] = {
{}
};
+void
+gp100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
+ u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10));
+ u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10));
+ u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10));
+ struct nvkm_fault_data info;
+
+ info.inst = (u64)inst << 12;
+ info.addr = ((u64)vahi << 32) | valo;
+ info.time = 0;
+ info.engine = unit;
+ info.valid = 1;
+ info.gpc = (type & 0x1f000000) >> 24;
+ info.hub = (type & 0x00100000) >> 20;
+ info.access = (type & 0x00070000) >> 16;
+ info.client = (type & 0x00007f00) >> 8;
+ info.reason = (type & 0x0000001f);
+
+ nvkm_fifo_fault(fifo, &info);
+}
+
static const struct gk104_fifo_func
gp100_fifo = {
+ .intr.fault = gp100_fifo_intr_fault,
.pbdma = &gm200_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gp100_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c
index 778ba7e46fb3..8c65ad4feedb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c
@@ -26,6 +26,7 @@
static const struct gk104_fifo_func
gp10b_fifo = {
+ .intr.fault = gp100_fifo_intr_fault,
.pbdma = &gm200_fifo_pbdma,
.fault.access = gk104_fifo_fault_access,
.fault.engine = gp100_fifo_fault_engine,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
index c66f5370b21f..0ef8baab513e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
@@ -37,4 +37,6 @@ struct nvkm_fifo_func {
void nv04_fifo_intr(struct nvkm_fifo *);
void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *);
void nv04_fifo_start(struct nvkm_fifo *, unsigned long *);
+
+void gf100_fifo_intr_fault(struct nvkm_fifo *, int);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c
index 950bff1955ad..1ed6170891c4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c
@@ -26,7 +26,6 @@ gm20b_bar_func = {
.dtor = gf100_bar_dtor,
.oneinit = gf100_bar_oneinit,
.bar1.init = gf100_bar_bar1_init,
- .bar1.fini = gf100_bar_bar1_fini,
.bar1.wait = gm107_bar_bar1_wait,
.bar1.vmm = gf100_bar_bar1_vmm,
.flush = g84_bar_flush,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c
index b8578359e61b..118e33174cbe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c
@@ -46,6 +46,19 @@ extdev_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt)
return extdev + *hdr;
}
+bool
+nvbios_extdev_skip_probe(struct nvkm_bios *bios)
+{
+ u8 ver, hdr, len, cnt;
+ u16 data = extdev_table(bios, &ver, &hdr, &len, &cnt);
+ if (data && ver == 0x40 && hdr >= 5) {
+ u8 flags = nvbios_rd08(bios, data - hdr + 4);
+ if (flags & 1)
+ return true;
+ }
+ return false;
+}
+
static u16
nvbios_extdev_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
index ec0e9f7224b5..9de74f41dcd2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
@@ -834,7 +834,7 @@ init_generic_condition(struct nvbios_init *init)
init_exec_set(init, false);
break;
default:
- warn("INIT_GENERIC_CONDITON: unknown 0x%02x\n", cond);
+ warn("INIT_GENERIC_CONDITION: unknown 0x%02x\n", cond);
init->offset += size;
break;
}
@@ -1935,6 +1935,28 @@ init_ram_restrict_pll(struct nvbios_init *init)
}
/**
+ * INIT_RESET_BEGUN - opcode 0x8c
+ *
+ */
+static void
+init_reset_begun(struct nvbios_init *init)
+{
+ trace("RESET_BEGUN\n");
+ init->offset += 1;
+}
+
+/**
+ * INIT_RESET_END - opcode 0x8d
+ *
+ */
+static void
+init_reset_end(struct nvbios_init *init)
+{
+ trace("RESET_END\n");
+ init->offset += 1;
+}
+
+/**
* INIT_GPIO - opcode 0x8e
*
*/
@@ -2260,8 +2282,8 @@ static struct nvbios_init_opcode {
[0x79] = { init_pll },
[0x7a] = { init_zm_reg },
[0x87] = { init_ram_restrict_pll },
- [0x8c] = { init_reserved },
- [0x8d] = { init_reserved },
+ [0x8c] = { init_reset_begun },
+ [0x8d] = { init_reset_end },
[0x8e] = { init_gpio },
[0x8f] = { init_ram_restrict_zm_reg_group },
[0x90] = { init_copy_zm_reg },
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
index 7143ea4611aa..33a9fb5ac558 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
@@ -96,6 +96,8 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
info->min = min(info->base,
info->base + info->step * info->vidmask);
info->max = nvbios_rd32(bios, volt + 0x0e);
+ if (!info->max)
+ info->max = max(info->base, info->base + info->step * info->vidmask);
break;
case 0x50:
info->min = nvbios_rd32(bios, volt + 0x0a);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
index 1399d923d446..914276410ef8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
@@ -23,6 +23,7 @@
*/
#include "priv.h"
+#include <core/option.h>
#include <core/notify.h>
static int
@@ -182,12 +183,43 @@ static const struct dmi_system_id gpio_reset_ids[] = {
{ }
};
+static enum dcb_gpio_func_name power_checks[] = {
+ DCB_GPIO_THERM_EXT_POWER_EVENT,
+ DCB_GPIO_POWER_ALERT,
+ DCB_GPIO_EXT_POWER_LOW,
+};
+
static int
nvkm_gpio_init(struct nvkm_subdev *subdev)
{
struct nvkm_gpio *gpio = nvkm_gpio(subdev);
+ struct dcb_gpio_func func;
+ int ret;
+ int i;
+
if (dmi_check_system(gpio_reset_ids))
nvkm_gpio_reset(gpio, DCB_GPIO_UNUSED);
+
+ if (nvkm_boolopt(subdev->device->cfgopt, "NvPowerChecks", true)) {
+ for (i = 0; i < ARRAY_SIZE(power_checks); ++i) {
+ ret = nvkm_gpio_find(gpio, 0, power_checks[i],
+ DCB_GPIO_UNUSED, &func);
+ if (ret)
+ continue;
+
+ ret = nvkm_gpio_get(gpio, 0, func.func, func.line);
+ if (!ret)
+ continue;
+
+ nvkm_error(&gpio->subdev,
+ "GPU is missing power, check its power "
+ "cables. Boot with "
+ "nouveau.config=NvPowerChecks=0 to "
+ "disable.\n");
+ return -EINVAL;
+ }
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
index b4e7404fe660..a11637b0f6cc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
@@ -40,8 +40,7 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
u8 *ptr = msg->buf;
while (remaining) {
- u8 cnt = (remaining > 16) ? 16 : remaining;
- u8 cmd;
+ u8 cnt, retries, cmd;
if (msg->flags & I2C_M_RD)
cmd = 1;
@@ -51,10 +50,19 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (mcnt || remaining > 16)
cmd |= 4; /* MOT */
- ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, &cnt);
- if (ret < 0) {
- nvkm_i2c_aux_release(aux);
- return ret;
+ for (retries = 0, cnt = 0;
+ retries < 32 && !cnt;
+ retries++) {
+ cnt = min_t(u8, remaining, 16);
+ ret = aux->func->xfer(aux, true, cmd,
+ msg->addr, ptr, &cnt);
+ if (ret < 0)
+ goto out;
+ }
+ if (!cnt) {
+ AUX_TRACE(aux, "no data after 32 retries");
+ ret = -EIO;
+ goto out;
}
ptr += cnt;
@@ -64,8 +72,10 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
msg++;
}
+ ret = num;
+out:
nvkm_i2c_aux_release(aux);
- return num;
+ return ret;
}
static u32
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
index ce70a193caa7..ea2e11771bca 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
@@ -26,6 +26,24 @@
#include <core/msgqueue.h>
#include <subdev/timer.h>
+bool
+nvkm_pmu_fan_controlled(struct nvkm_device *device)
+{
+ struct nvkm_pmu *pmu = device->pmu;
+
+ /* Internal PMU FW does not currently control fans in any way,
+ * allow SW control of fans instead.
+ */
+ if (pmu && pmu->func->code.size)
+ return false;
+
+ /* Default (board-loaded, or VBIOS PMU/PREOS) PMU FW on Fermi
+ * and newer automatically control the fan speed, which would
+ * interfere with SW control.
+ */
+ return (device->chipset >= 0xc0);
+}
+
void
nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index 4fd4cfe459b8..7af971db91bc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -1088,7 +1088,7 @@ acr_r352_ls_gpccs_func_0 = {
.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD,
};
-const struct acr_r352_ls_func
+static const struct acr_r352_ls_func
acr_r352_ls_gpccs_func = {
.load = acr_ls_ucode_load_gpccs,
.version_max = 0,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c
index 84a2f243ed9b..4695f1c8e33f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c
@@ -190,6 +190,9 @@ MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin");
MODULE_FIRMWARE("nvidia/gp104/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gp104/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/gp104/acr/ucode_load.bin");
@@ -210,6 +213,9 @@ MODULE_FIRMWARE("nvidia/gp104/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin");
MODULE_FIRMWARE("nvidia/gp106/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gp106/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/gp106/acr/ucode_load.bin");
@@ -230,6 +236,9 @@ MODULE_FIRMWARE("nvidia/gp106/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin");
MODULE_FIRMWARE("nvidia/gp107/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gp107/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/gp107/acr/ucode_load.bin");
@@ -250,3 +259,6 @@ MODULE_FIRMWARE("nvidia/gp107/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin");
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
index 07914e36939e..4a4d1e224126 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
@@ -21,9 +21,11 @@
*
* Authors: Martin Peres
*/
-#include <nvkm/core/option.h>
#include "priv.h"
+#include <core/option.h>
+#include <subdev/pmu.h>
+
int
nvkm_therm_temp_get(struct nvkm_therm *therm)
{
@@ -192,8 +194,7 @@ nvkm_therm_fan_mode(struct nvkm_therm *therm, int mode)
/* The default PPWR ucode on fermi interferes with fan management */
if ((mode >= ARRAY_SIZE(name)) ||
- (mode != NVKM_THERM_CTRL_NONE && device->card_type >= NV_C0 &&
- !device->pmu))
+ (mode != NVKM_THERM_CTRL_NONE && nvkm_pmu_fan_controlled(device)))
return -EINVAL;
/* do not allow automatic fan management if the thermal sensor is
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
index 6e0ddc1bb583..03b355dabab3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c
@@ -116,6 +116,9 @@ nvkm_therm_ic_ctor(struct nvkm_therm *therm)
return;
}
+ if (nvbios_extdev_skip_probe(bios))
+ return;
+
/* The vbios doesn't provide the address of an exisiting monitoring
device. Let's try our static list.
*/