diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
76 files changed, 839 insertions, 411 deletions
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 5713bacaee80..dc64863b5fd8 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 5c36c75232e6..b46be8a091e9 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> @@ -1603,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, @@ -1830,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); @@ -1917,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); } @@ -1983,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 @@ -1997,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); @@ -2038,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); @@ -2320,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 283ff690350e..2db029371c91 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; } @@ -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,6 +372,16 @@ 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; } @@ -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; } @@ -457,7 +501,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) asyw->image.handle[0] = ctxdma->object.handle; } - asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.resv); + asyw->state.fence = dma_resv_get_excl_rcu(fb->nvbo->bo.base.resv); asyw->image.offset[0] = fb->nvbo->bo.offset; if (wndw->func->prepare) { @@ -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_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index c3fd5dd39ed9..e2bae1424502 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -139,7 +139,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, if (chan->ntfy) { nouveau_vma_del(&chan->ntfy_vma); nouveau_bo_unpin(chan->ntfy); - drm_gem_object_put_unlocked(&chan->ntfy->gem); + drm_gem_object_put_unlocked(&chan->ntfy->bo.base); } if (chan->heap.block_size) @@ -245,12 +245,6 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) } int -nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS) -{ - return -EINVAL; -} - -int nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) { struct drm_nouveau_channel_alloc *init = data; @@ -345,7 +339,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) goto done; } - ret = drm_gem_handle_create(file_priv, &chan->ntfy->gem, + ret = drm_gem_handle_create(file_priv, &chan->ntfy->bo.base, &init->notifier_handle); if (ret) goto done; diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index 195546719bfe..70f6aa5c9dd1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -6,7 +6,6 @@ struct drm_device *dev, void *data, struct drm_file *file_priv int nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS); -int nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS); 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 34a998012bf6..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->gem.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); } @@ -185,31 +191,24 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, *size = roundup_64(*size, PAGE_SIZE); } -int -nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, - uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, - struct sg_table *sg, struct reservation_object *robj, - struct nouveau_bo **pnvbo) +struct nouveau_bo * +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; struct nvif_mmu *mmu = &cli->mmu; struct nvif_vmm *vmm = cli->svm.cli ? &cli->svm.vmm : &cli->vmm.vmm; - size_t acc_size; - int type = ttm_bo_type_device; - int ret, i, pi = -1; + int i, pi = -1; - if (!size) { - NV_WARN(drm, "skipped size %016llx\n", size); - return -EINVAL; + if (!*size) { + NV_WARN(drm, "skipped size %016llx\n", *size); + return ERR_PTR(-EINVAL); } - if (sg) - type = ttm_bo_type_sg; - nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); if (!nvbo) - return -ENOMEM; + return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&nvbo->head); INIT_LIST_HEAD(&nvbo->entry); INIT_LIST_HEAD(&nvbo->vma_list); @@ -231,7 +230,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, nvbo->kind = (tile_flags & 0x0000ff00) >> 8; if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { kfree(nvbo); - return -EINVAL; + return ERR_PTR(-EINVAL); } nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind; @@ -241,7 +240,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, nvbo->comp = (tile_flags & 0x00030000) >> 16; if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { kfree(nvbo); - return -EINVAL; + return ERR_PTR(-EINVAL); } } else { nvbo->zeta = (tile_flags & 0x00000007); @@ -273,12 +272,12 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, 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; } if (WARN_ON(pi < 0)) - return -EINVAL; + return ERR_PTR(-EINVAL); /* Disable compression if suitable settings couldn't be found. */ if (nvbo->comp && !vmm->page[pi].comp) { @@ -288,22 +287,53 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, } nvbo->page = vmm->page[pi].shift; - nouveau_bo_fixup_align(nvbo, flags, &align, &size); + nouveau_bo_fixup_align(nvbo, flags, align, size); + + return nvbo; +} + +int +nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 flags, + struct sg_table *sg, struct dma_resv *robj) +{ + int type = sg ? ttm_bo_type_sg : ttm_bo_type_device; + size_t acc_size; + int ret; + + acc_size = ttm_bo_dma_acc_size(nvbo->bo.bdev, size, sizeof(*nvbo)); + nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; nouveau_bo_placement_set(nvbo, flags, 0); - acc_size = ttm_bo_dma_acc_size(&drm->ttm.bdev, size, - sizeof(struct nouveau_bo)); - - ret = ttm_bo_init(&drm->ttm.bdev, &nvbo->bo, size, - type, &nvbo->placement, - align >> PAGE_SHIFT, false, acc_size, sg, - robj, nouveau_bo_del_ttm); + ret = ttm_bo_init(nvbo->bo.bdev, &nvbo->bo, size, type, + &nvbo->placement, align >> PAGE_SHIFT, false, + acc_size, sg, robj, nouveau_bo_del_ttm); if (ret) { /* ttm will call nouveau_bo_del_ttm if it fails.. */ return ret; } + return 0; +} + +int +nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, + uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, + struct sg_table *sg, struct dma_resv *robj, + struct nouveau_bo **pnvbo) +{ + struct nouveau_bo *nvbo; + int ret; + + nvbo = nouveau_bo_alloc(cli, &size, &align, flags, tile_mode, + tile_flags); + if (IS_ERR(nvbo)) + return PTR_ERR(nvbo); + + ret = nouveau_bo_init(nvbo, size, align, flags, sg, robj); + if (ret) + return ret; + *pnvbo = nvbo; return 0; } @@ -1323,7 +1353,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct drm_device *dev = drm->dev; - struct dma_fence *fence = reservation_object_get_excl(bo->resv); + struct dma_fence *fence = dma_resv_get_excl(bo->base.resv); nv10_bo_put_tile_region(dev, *old_tile, fence); *old_tile = new_tile; @@ -1400,7 +1430,7 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) { struct nouveau_bo *nvbo = nouveau_bo(bo); - return drm_vma_node_verify_access(&nvbo->gem.vma_node, + return drm_vma_node_verify_access(&nvbo->bo.base.vma_node, filp->private_data); } @@ -1654,12 +1684,12 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) void nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool exclusive) { - struct reservation_object *resv = nvbo->bo.resv; + struct dma_resv *resv = nvbo->bo.base.resv; if (exclusive) - reservation_object_add_excl_fence(resv, &fence->base); + dma_resv_add_excl_fence(resv, &fence->base); else if (fence) - reservation_object_add_shared_fence(resv, &fence->base); + dma_resv_add_shared_fence(resv, &fence->base); } struct ttm_bo_driver nouveau_bo_driver = { diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index 383ac36d5869..38f9d8350963 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -35,11 +35,6 @@ struct nouveau_bo { struct nouveau_drm_tile *tile; - /* Only valid if allocated via nouveau_gem_new() and iff you hold a - * gem reference to it! For debugging, use gem.filp != NULL to test - * whether it is valid. */ - struct drm_gem_object gem; - /* protect by the ttm reservation lock */ int pin_refcnt; @@ -76,9 +71,13 @@ 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, 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, u32 tile_mode, u32 tile_flags, struct sg_table *sg, - struct reservation_object *robj, + struct dma_resv *robj, struct nouveau_bo **); int nouveau_bo_pin(struct nouveau_bo *, u32 flags, bool contig); int nouveau_bo_unpin(struct nouveau_bo *); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 8f15281faa79..94dfa2e5a9ab 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> @@ -1349,7 +1348,7 @@ nouveau_connector_create(struct drm_device *dev, break; case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_eDP: - nv_connector->aux.dev = dev->dev; + nv_connector->aux.dev = connector->kdev; nv_connector->aux.transfer = nouveau_connector_aux_xfer; snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x", dcbe->hasht, dcbe->hashm); 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 832da8e0020d..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" @@ -201,7 +203,7 @@ nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); if (fb->nvbo) - drm_gem_object_put_unlocked(&fb->nvbo->gem); + drm_gem_object_put_unlocked(&fb->nvbo->bo.base); drm_framebuffer_cleanup(drm_fb); kfree(fb); @@ -214,7 +216,7 @@ nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb, { struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); - return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle); + return drm_gem_handle_create(file_priv, &fb->nvbo->bo.base, handle); } static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { @@ -660,8 +662,8 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, if (ret) return ret; - ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); - drm_gem_object_put_unlocked(&bo->gem); + ret = drm_gem_handle_create(file_priv, &bo->bo.base, &args->handle); + drm_gem_object_put_unlocked(&bo->bo.base); return ret; } @@ -675,7 +677,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv, gem = drm_gem_object_lookup(file_priv, handle); if (gem) { struct nouveau_bo *bo = nouveau_gem_object(gem); - *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); + *poffset = drm_vma_node_offset_addr(&bo->bo.base.vma_node); drm_gem_object_put_unlocked(gem); return 0; } 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_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 7c2fcaba42d6..bdc948352467 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -29,8 +29,9 @@ #include <linux/pm_runtime.h> #include <linux/vga_switcheroo.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> @@ -1046,20 +1047,20 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) static const struct drm_ioctl_desc nouveau_ioctls[] = { - DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_INIT, nouveau_svmm_init, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_BIND, nouveau_svmm_bind, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_INIT, nouveau_svmm_init, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_BIND, nouveau_svmm_bind, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_RENDER_ALLOW), }; long @@ -1105,7 +1106,7 @@ nouveau_driver_fops = { static struct drm_driver driver_stub = { .driver_features = - DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER + DRIVER_GEM | DRIVER_MODESET | DRIVER_RENDER #if defined(CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT) | DRIVER_KMS_LEGACY_CONTEXT #endif @@ -1130,10 +1131,7 @@ driver_stub = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = nouveau_gem_prime_pin, - .gem_prime_res_obj = nouveau_gem_prime_res_obj, .gem_prime_unpin = nouveau_gem_prime_unpin, .gem_prime_get_sg_table = nouveau_gem_prime_get_sg_table, .gem_prime_import_sg_table = nouveau_gem_prime_import_sg_table, 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 d4964f3397a1..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> @@ -335,20 +334,20 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e { struct nouveau_fence_chan *fctx = chan->fence; struct dma_fence *fence; - struct reservation_object *resv = nvbo->bo.resv; - struct reservation_object_list *fobj; + struct dma_resv *resv = nvbo->bo.base.resv; + struct dma_resv_list *fobj; struct nouveau_fence *f; int ret = 0, i; if (!exclusive) { - ret = reservation_object_reserve_shared(resv, 1); + ret = dma_resv_reserve_shared(resv, 1); if (ret) return ret; } - fobj = reservation_object_get_list(resv); - fence = reservation_object_get_excl(resv); + fobj = dma_resv_get_list(resv); + fence = dma_resv_get_excl(resv); if (fence && (!exclusive || !fobj || !fobj->shared_count)) { struct nouveau_channel *prev = NULL; @@ -377,7 +376,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e bool must_wait = true; fence = rcu_dereference_protected(fobj->shared[i], - reservation_object_held(resv)); + dma_resv_held(resv)); f = nouveau_local_fence(fence, chan->drm); if (f) { diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index b4bda716564d..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,11 +184,24 @@ 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; - ret = nouveau_bo_new(cli, size, align, flags, tile_mode, - tile_flags, NULL, NULL, pnvbo); - if (ret) + nvbo = nouveau_bo_alloc(cli, &size, &align, flags, tile_mode, + tile_flags); + if (IS_ERR(nvbo)) + return PTR_ERR(nvbo); + + /* Initialize the embedded gem-object. We return a single gem-reference + * to the caller, instead of a normal nouveau_bo ttm reference. */ + ret = drm_gem_object_init(drm->dev, &nvbo->bo.base, size); + if (ret) { + nouveau_bo_ref(NULL, &nvbo); return ret; - nvbo = *pnvbo; + } + + ret = nouveau_bo_init(nvbo, size, align, flags, NULL, NULL); + if (ret) { + nouveau_bo_ref(NULL, &nvbo); + return ret; + } /* we restrict allowed domains on nv50+ to only the types * that were requested at creation time. not possibly on @@ -203,15 +212,8 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) nvbo->valid_domains &= domain; - /* Initialize the embedded gem-object. We return a single gem-reference - * to the caller, instead of a normal nouveau_bo ttm reference. */ - ret = drm_gem_object_init(drm->dev, &nvbo->gem, nvbo->bo.mem.size); - if (ret) { - nouveau_bo_ref(NULL, pnvbo); - return -ENOMEM; - } - - nvbo->bo.persistent_swap_storage = nvbo->gem.filp; + nvbo->bo.persistent_swap_storage = nvbo->bo.base.filp; + *pnvbo = nvbo; return 0; } @@ -240,7 +242,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, } rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; - rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node); + rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.base.vma_node); rep->tile_mode = nvbo->mode; rep->tile_flags = nvbo->contig ? 0 : NOUVEAU_GEM_TILE_NONCONTIG; if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) @@ -268,15 +270,16 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, if (ret) return ret; - ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle); + ret = drm_gem_handle_create(file_priv, &nvbo->bo.base, + &req->info.handle); if (ret == 0) { - ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info); + ret = nouveau_gem_info(file_priv, &nvbo->bo.base, &req->info); if (ret) drm_gem_handle_delete(file_priv, req->info.handle); } /* drop reference from allocate - handle holds it now */ - drm_gem_object_put_unlocked(&nvbo->gem); + drm_gem_object_put_unlocked(&nvbo->bo.base); return ret; } @@ -355,7 +358,7 @@ validate_fini_no_ticket(struct validate_op *op, struct nouveau_channel *chan, list_del(&nvbo->entry); nvbo->reserved_by = NULL; ttm_bo_unreserve(&nvbo->bo); - drm_gem_object_put_unlocked(&nvbo->gem); + drm_gem_object_put_unlocked(&nvbo->bo.base); } } @@ -493,7 +496,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, list_for_each_entry(nvbo, list, entry) { struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; - ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains, + ret = nouveau_gem_set_domain(&nvbo->bo.base, b->read_domains, b->write_domains, b->valid_domains); if (unlikely(ret)) { @@ -886,7 +889,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, return -ENOENT; nvbo = nouveau_gem_object(gem); - lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, + lret = dma_resv_wait_timeout_rcu(nvbo->bo.base.resv, write, true, no_wait ? 0 : 30 * HZ); if (!lret) ret = -EBUSY; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h index 03371204a47c..978e07591990 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.h +++ b/drivers/gpu/drm/nouveau/nouveau_gem.h @@ -2,15 +2,13 @@ #ifndef __NOUVEAU_GEM_H__ #define __NOUVEAU_GEM_H__ -#include <drm/drmP.h> - #include "nouveau_drv.h" #include "nouveau_bo.h" static inline struct nouveau_bo * nouveau_gem_object(struct drm_gem_object *gem) { - return gem ? container_of(gem, struct nouveau_bo, gem) : NULL; + return gem ? container_of(gem, struct nouveau_bo, bo.base) : NULL; } /* nouveau_gem.c */ @@ -33,7 +31,6 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *, struct drm_file *); extern int nouveau_gem_prime_pin(struct drm_gem_object *); -struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *); extern void nouveau_gem_prime_unpin(struct drm_gem_object *); extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *); extern struct drm_gem_object *nouveau_gem_prime_import_sg_table( 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 1fefc93af1d7..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,31 +60,46 @@ 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 reservation_object *robj = attach->dmabuf->resv; + struct dma_resv *robj = attach->dmabuf->resv; + u64 size = attach->dmabuf->size; u32 flags = 0; + int align = 0; int ret; flags = TTM_PL_FLAG_TT; - ww_mutex_lock(&robj->lock, NULL); - ret = nouveau_bo_new(&drm->client, attach->dmabuf->size, 0, flags, 0, 0, - sg, robj, &nvbo); - ww_mutex_unlock(&robj->lock); - if (ret) - return ERR_PTR(ret); + dma_resv_lock(robj, NULL); + 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; /* Initialize the embedded gem-object. We return a single gem-reference * to the caller, instead of a normal nouveau_bo ttm reference. */ - ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size); + ret = drm_gem_object_init(dev, &nvbo->bo.base, size); + if (ret) { + nouveau_bo_ref(NULL, &nvbo); + obj = ERR_PTR(-ENOMEM); + goto unlock; + } + + ret = nouveau_bo_init(nvbo, size, align, flags, sg, robj); if (ret) { nouveau_bo_ref(NULL, &nvbo); - return ERR_PTR(-ENOMEM); + obj = ERR_PTR(ret); + goto unlock; } - return &nvbo->gem; + obj = &nvbo->bo.base; + +unlock: + dma_resv_unlock(robj); + return obj; } int nouveau_gem_prime_pin(struct drm_gem_object *obj) @@ -107,10 +121,3 @@ void nouveau_gem_prime_unpin(struct drm_gem_object *obj) nouveau_bo_unpin(nvbo); } - -struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *obj) -{ - struct nouveau_bo *nvbo = nouveau_gem_object(obj); - - return nvbo->bo.resv; -} 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/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/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. */ |