diff options
author | Dave Airlie <airlied@redhat.com> | 2021-11-23 09:38:29 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2021-11-23 09:38:55 +1000 |
commit | c18c8891111bb5e014e144716044991112f16833 (patch) | |
tree | c14b9d7002468c04d802af02bf69aae50d14075a /drivers/gpu/drm/nouveau | |
parent | 136057256686de39cc3a07c2e39ef6bc43003ff6 (diff) | |
parent | a713ca234ea9d946235ac7248995c5fddfd9e523 (diff) | |
download | linux-c18c8891111bb5e014e144716044991112f16833.tar.bz2 |
Merge tag 'drm-misc-next-2021-11-18' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.17:
UAPI Changes:
* Remove restrictions on DMA_BUF_SET_NAME ioctl
* connector: State of privacy screen
* sysfs: Send hotplug uevent
Cross-subsystem Changes:
* clk/bmc-2835: Fixes
* dma-buf: Add dma_resv selftest; Error-handling fixes; Add debugfs
helpers; Remove dma_resv_get_excl_unlocked(); Documentation fixes
* pwm: Introduce of_pwm_single_xlate()
Core Changes:
* Support for privacy screens
* Make drm_irq.c legacy
* Fix __stack_depot_* name conflict
* Documentation fixes
* Fixes and cleanups
* dp-helper: Reuse 8b/10b link-training delay helpers
* format-helper: Update interfaces
* fb-helper: Allocate shadow buffer of correct size
* gem: Link GEM SHMEM and CMA helpers into separate modules; Use
dma_resv iterator; Import DMA_BUF namespace into GEM-helper modules
* gem/shmem-helper: Interface cleanups
* scheduler: Grab fence in drm_sched_job_add_implicit_dependencies();
Lockdep fixes
* kms-helpers: Link several files from core into the KMS-helper module
Driver Changes:
* Use dma_resv_iter in several places
* Fixes and cleanups
* amdgpu: Use drm_kms_helper_connector_hotplug_event(); Get all fences
at once
* bridge: Switch to managed MIPI DSI helpers in several places; Register
and attach during probe in several places; Convert to YAML in several
places
* bridge/anx7625: Support MIPI DPI input; Support HDMI audio; Fixes
* bridge/dw-hdmi: Allow interlace on bridge
* bridge/ps8640: Enable PM; Support aux-bus
* bridge/tc358768: Enabled reference clock; Support pulse mode;
Modesetting fixes
* bridge/ti-sn65dsi86: Use regmap_bulk_write(); Implement PWM
* etnaviv: Get all fences at once
* gma500: GEM object cleanups; Remove generic drivers in probe function
* i915: Support VESA panel backlights
* ingenic: Fixes and cleanups
* kirin: Adjust probe order
* kmb: Enable framebuffer console
* lima: Kconfig fixes
* meson: Refactoring to supperot DRM_BRIDGE_ATTACH_NO_ENCODER
* msm: Fixes and cleanups
* msm/dsi: Adjust probe order
* omap: Fixes and cleanups
* nouveau: CRC fixes; Validate LUTs in atomic check; Set HDMI AVI RGB
quantization to FULL; Fixes and cleanups
* panel: Support Innolux G070Y2-T02, Vivax TPC-9150, JDI R63452,
Newhaven 1.8-128160EF, Wanchanglong W552964ABA, Novatek NT35950,
BOE BF060Y8M, Sony Tulip Truly NT35521; Use dev_err_probe() throughout
drivers; Fixes and cleanups
* panel/ili9881c: Orientation fixes
* radeon: Use dma_resv_wait_timeout()
* rockchip: Add timeout for DSP hold; Suspend/resume fixes; PLL clock
fixes; Implement mmap in GEM object functions
* simpledrm: Support FB_DAMAGE_CLIPS and virtual screen sizes
* sun4i: Use CMA helpers without vmap support
* tidss: Fixes and cleanups
* v3d: Cleanups
* vc4: Fix HDMI-CEC hang when display is off; Power on HDMI controller
while disabling; Support 4k@60 Hz modes; Fixes and cleanups
* video: Convert to sysfs_emit() in several places
* video/omapfb: Fix fall-through
* virtio: Overflow fixes
* xen: Implement mmap as GEM object functions
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/YZYZSypIrr+qcih3@linux-uq9g.fritz.box
Diffstat (limited to 'drivers/gpu/drm/nouveau')
41 files changed, 376 insertions, 200 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 7739f46470d3..99fee4d8cd31 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -205,7 +205,7 @@ nv04_display_destroy(struct drm_device *dev) nvif_notify_dtor(&disp->flip); nouveau_display(dev)->priv = NULL; - kfree(disp); + vfree(disp); nvif_object_unmap(&drm->client.device.object); } @@ -223,7 +223,7 @@ nv04_display_create(struct drm_device *dev) struct nv04_display *disp; int i, ret; - disp = kzalloc(sizeof(*disp), GFP_KERNEL); + disp = vzalloc(sizeof(*disp)); if (!disp) return -ENOMEM; diff --git a/drivers/gpu/drm/nouveau/dispnv50/Kbuild b/drivers/gpu/drm/nouveau/dispnv50/Kbuild index 4488e1c061b3..28be2912ff74 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/Kbuild +++ b/drivers/gpu/drm/nouveau/dispnv50/Kbuild @@ -13,6 +13,7 @@ nouveau-y += dispnv50/corec57d.o nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crc.o nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crc907d.o nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crcc37d.o +nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crcc57d.o nouveau-y += dispnv50/dac507d.o nouveau-y += dispnv50/dac907d.o diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c index 5396e3707cc4..e6b0417c325b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base907c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c @@ -103,12 +103,9 @@ base907c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) return 0; } -static bool +static void base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) { - if (size != 256 && size != 1024) - return false; - if (size == 1024) asyw->xlut.i.mode = NV907C_SET_BASE_LUT_LO_MODE_INTERPOLATE_1025_UNITY_RANGE; else @@ -116,7 +113,6 @@ base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) asyw->xlut.i.enable = NV907C_SET_BASE_LUT_LO_ENABLE_ENABLE; asyw->xlut.i.load = head907d_olut_load; - return true; } static inline u32 diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c index 75876546eac1..53b1e2a569c1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c @@ -69,7 +69,7 @@ corec57d = { .head = &headc57d, .sor = &sorc37d, #if IS_ENABLED(CONFIG_DEBUG_FS) - .crc = &crcc37d, + .crc = &crcc57d, #endif }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.c b/drivers/gpu/drm/nouveau/dispnv50/crc.c index 66f32d965c72..29428e770f14 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crc.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crc.c @@ -84,7 +84,10 @@ static void nv50_crc_ctx_flip_work(struct kthread_work *base) struct nv50_crc *crc = container_of(work, struct nv50_crc, flip_work); struct nv50_head *head = container_of(crc, struct nv50_head, crc); struct drm_crtc *crtc = &head->base.base; - struct nv50_disp *disp = nv50_disp(crtc->dev); + struct drm_device *dev = crtc->dev; + struct nv50_disp *disp = nv50_disp(dev); + const uint64_t start_vbl = drm_crtc_vblank_count(crtc); + uint64_t end_vbl; u8 new_idx = crc->ctx_idx ^ 1; /* @@ -92,23 +95,24 @@ static void nv50_crc_ctx_flip_work(struct kthread_work *base) * try again for the next vblank if we don't grab the lock */ if (!mutex_trylock(&disp->mutex)) { - DRM_DEV_DEBUG_KMS(crtc->dev->dev, - "Lock contended, delaying CRC ctx flip for head-%d\n", - head->base.index); - drm_vblank_work_schedule(work, - drm_crtc_vblank_count(crtc) + 1, - true); + drm_dbg_kms(dev, "Lock contended, delaying CRC ctx flip for %s\n", crtc->name); + drm_vblank_work_schedule(work, start_vbl + 1, true); return; } - DRM_DEV_DEBUG_KMS(crtc->dev->dev, - "Flipping notifier ctx for head %d (%d -> %d)\n", - drm_crtc_index(crtc), crc->ctx_idx, new_idx); + drm_dbg_kms(dev, "Flipping notifier ctx for %s (%d -> %d)\n", + crtc->name, crc->ctx_idx, new_idx); nv50_crc_program_ctx(head, NULL); nv50_crc_program_ctx(head, &crc->ctx[new_idx]); mutex_unlock(&disp->mutex); + end_vbl = drm_crtc_vblank_count(crtc); + if (unlikely(end_vbl != start_vbl)) + NV_ERROR(nouveau_drm(dev), + "Failed to flip CRC context on %s on time (%llu > %llu)\n", + crtc->name, end_vbl, start_vbl); + spin_lock_irq(&crc->lock); crc->ctx_changed = true; spin_unlock_irq(&crc->lock); @@ -189,9 +193,9 @@ void nv50_crc_handle_vblank(struct nv50_head *head) * updates back-to-back without waiting, we'll just be * optimistic and assume we always miss exactly one frame. */ - DRM_DEV_DEBUG_KMS(head->base.base.dev->dev, - "Notifier ctx flip for head-%d finished, lost CRC for frame %llu\n", - head->base.index, crc->frame); + drm_dbg_kms(head->base.base.dev, + "Notifier ctx flip for head-%d finished, lost CRC for frame %llu\n", + head->base.index, crc->frame); crc->frame++; nv50_crc_reset_ctx(ctx); @@ -347,8 +351,6 @@ int nv50_crc_atomic_check_head(struct nv50_head *head, struct nv50_head_atom *armh) { struct nv50_atom *atom = nv50_atom(asyh->state.state); - struct drm_device *dev = head->base.base.dev; - struct nv50_disp *disp = nv50_disp(dev); bool changed = armh->crc.src != asyh->crc.src; if (!armh->crc.src && !asyh->crc.src) { @@ -357,30 +359,7 @@ int nv50_crc_atomic_check_head(struct nv50_head *head, return 0; } - /* While we don't care about entry tags, Volta+ hw always needs the - * controlling wndw channel programmed to a wndw that's owned by our - * head - */ - if (asyh->crc.src && disp->disp->object.oclass >= GV100_DISP && - !(BIT(asyh->crc.wndw) & asyh->wndw.owned)) { - if (!asyh->wndw.owned) { - /* TODO: once we support flexible channel ownership, - * we should write some code here to handle attempting - * to "steal" a plane: e.g. take a plane that is - * currently not-visible and owned by another head, - * and reassign it to this head. If we fail to do so, - * we shuld reject the mode outright as CRC capture - * then becomes impossible. - */ - NV_ATOMIC(nouveau_drm(dev), - "No available wndws for CRC readback\n"); - return -EINVAL; - } - asyh->crc.wndw = ffs(asyh->wndw.owned) - 1; - } - - if (drm_atomic_crtc_needs_modeset(&asyh->state) || changed || - armh->crc.wndw != asyh->crc.wndw) { + if (drm_atomic_crtc_needs_modeset(&asyh->state) || changed) { asyh->clr.crc = armh->crc.src && armh->state.active; asyh->set.crc = asyh->crc.src && asyh->state.active; if (changed) @@ -467,9 +446,8 @@ void nv50_crc_atomic_set(struct nv50_head *head, struct nouveau_encoder *outp = nv50_real_outp(nv50_head_atom_get_encoder(asyh)); - func->set_src(head, outp->or, - nv50_crc_source_type(outp, asyh->crc.src), - &crc->ctx[crc->ctx_idx], asyh->crc.wndw); + func->set_src(head, outp->or, nv50_crc_source_type(outp, asyh->crc.src), + &crc->ctx[crc->ctx_idx]); } void nv50_crc_atomic_clr(struct nv50_head *head) @@ -477,7 +455,7 @@ void nv50_crc_atomic_clr(struct nv50_head *head) const struct nv50_crc_func *func = nv50_disp(head->base.base.dev)->core->func->crc; - func->set_src(head, 0, NV50_CRC_SOURCE_TYPE_NONE, NULL, 0); + func->set_src(head, 0, NV50_CRC_SOURCE_TYPE_NONE, NULL); } static inline int diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.h b/drivers/gpu/drm/nouveau/dispnv50/crc.h index 4fce871b04c8..4823f1fde2dd 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crc.h +++ b/drivers/gpu/drm/nouveau/dispnv50/crc.h @@ -45,13 +45,11 @@ struct nv50_crc_notifier_ctx { struct nv50_crc_atom { enum nv50_crc_source src; - /* Only used for gv100+ */ - u8 wndw : 4; }; struct nv50_crc_func { - int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type, - struct nv50_crc_notifier_ctx *, u32 wndw); + int (*set_src)(struct nv50_head *, int or, enum nv50_crc_source_type type, + struct nv50_crc_notifier_ctx *ctx); int (*set_ctx)(struct nv50_head *, struct nv50_crc_notifier_ctx *); u32 (*get_entry)(struct nv50_head *, struct nv50_crc_notifier_ctx *, enum nv50_crc_source, int idx); @@ -95,6 +93,7 @@ void nv50_crc_atomic_clr(struct nv50_head *); extern const struct nv50_crc_func crc907d; extern const struct nv50_crc_func crcc37d; +extern const struct nv50_crc_func crcc57d; #else /* IS_ENABLED(CONFIG_DEBUG_FS) */ struct nv50_crc {}; diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc907d.c b/drivers/gpu/drm/nouveau/dispnv50/crc907d.c index 0fb0fdb9f119..f9ad641555b7 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crc907d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crc907d.c @@ -23,9 +23,8 @@ struct crc907d_notifier { } __packed; static int -crc907d_set_src(struct nv50_head *head, int or, - enum nv50_crc_source_type source, - struct nv50_crc_notifier_ctx *ctx, u32 wndw) +crc907d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source, + struct nv50_crc_notifier_ctx *ctx) { struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; @@ -33,7 +32,8 @@ crc907d_set_src(struct nv50_head *head, int or, NVDEF(NV907D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) | NVDEF(NV907D, HEAD_SET_CRC_CONTROL, TIMESTAMP_MODE, FALSE) | NVDEF(NV907D, HEAD_SET_CRC_CONTROL, SECONDARY_OUTPUT, NONE) | - NVDEF(NV907D, HEAD_SET_CRC_CONTROL, CRC_DURING_SNOOZE, DISABLE); + NVDEF(NV907D, HEAD_SET_CRC_CONTROL, CRC_DURING_SNOOZE, DISABLE) | + NVDEF(NV907D, HEAD_SET_CRC_CONTROL, WIDE_PIPE_CRC, ENABLE); int ret; switch (source) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c b/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c index 814e5bd97446..f10f6c484408 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c @@ -2,6 +2,7 @@ #include <drm/drm_crtc.h> #include "crc.h" +#include "crcc37d.h" #include "core.h" #include "disp.h" #include "head.h" @@ -10,38 +11,13 @@ #include <nvhw/class/clc37d.h> -#define CRCC37D_MAX_ENTRIES 2047 - -struct crcc37d_notifier { - u32 status; - - /* reserved */ - u32 :32; - u32 :32; - u32 :32; - u32 :32; - u32 :32; - u32 :32; - u32 :32; - - struct crcc37d_entry { - u32 status[2]; - u32 :32; /* reserved */ - u32 compositor_crc; - u32 rg_crc; - u32 output_crc[2]; - u32 :32; /* reserved */ - } entries[CRCC37D_MAX_ENTRIES]; -} __packed; - static int -crcc37d_set_src(struct nv50_head *head, int or, - enum nv50_crc_source_type source, - struct nv50_crc_notifier_ctx *ctx, u32 wndw) +crcc37d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source, + struct nv50_crc_notifier_ctx *ctx) { struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; - u32 crc_args = NVVAL(NVC37D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, wndw) | + u32 crc_args = NVVAL(NVC37D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, i * 4) | NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) | NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, SECONDARY_CRC, NONE) | NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, CRC_DURING_SNOOZE, DISABLE); @@ -75,8 +51,7 @@ crcc37d_set_src(struct nv50_head *head, int or, return 0; } -static int -crcc37d_set_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx) +int crcc37d_set_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx) { struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; @@ -89,9 +64,8 @@ crcc37d_set_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx) return 0; } -static u32 crcc37d_get_entry(struct nv50_head *head, - struct nv50_crc_notifier_ctx *ctx, - enum nv50_crc_source source, int idx) +u32 crcc37d_get_entry(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx, + enum nv50_crc_source source, int idx) { struct crcc37d_notifier __iomem *notifier = ctx->mem.object.map.ptr; struct crcc37d_entry __iomem *entry = ¬ifier->entries[idx]; @@ -105,8 +79,7 @@ static u32 crcc37d_get_entry(struct nv50_head *head, return ioread32_native(crc_addr); } -static bool crcc37d_ctx_finished(struct nv50_head *head, - struct nv50_crc_notifier_ctx *ctx) +bool crcc37d_ctx_finished(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx) { struct nouveau_drm *drm = nouveau_drm(head->base.base.dev); struct crcc37d_notifier __iomem *notifier = ctx->mem.object.map.ptr; @@ -148,7 +121,7 @@ const struct nv50_crc_func crcc37d = { .set_ctx = crcc37d_set_ctx, .get_entry = crcc37d_get_entry, .ctx_finished = crcc37d_ctx_finished, - .flip_threshold = CRCC37D_MAX_ENTRIES - 30, + .flip_threshold = CRCC37D_FLIP_THRESHOLD, .num_entries = CRCC37D_MAX_ENTRIES, .notifier_len = sizeof(struct crcc37d_notifier), }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/crcc37d.h b/drivers/gpu/drm/nouveau/dispnv50/crcc37d.h new file mode 100644 index 000000000000..5775137b832d --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/crcc37d.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __CRCC37D_H__ +#define __CRCC37D_H__ + +#include <linux/types.h> + +#include "crc.h" + +#define CRCC37D_MAX_ENTRIES 2047 +#define CRCC37D_FLIP_THRESHOLD (CRCC37D_MAX_ENTRIES - 30) + +struct crcc37d_notifier { + u32 status; + + /* reserved */ + u32:32; + u32:32; + u32:32; + u32:32; + u32:32; + u32:32; + u32:32; + + struct crcc37d_entry { + u32 status[2]; + u32:32; /* reserved */ + u32 compositor_crc; + u32 rg_crc; + u32 output_crc[2]; + u32:32; /* reserved */ + } entries[CRCC37D_MAX_ENTRIES]; +} __packed; + +int crcc37d_set_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx); +u32 crcc37d_get_entry(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx, + enum nv50_crc_source source, int idx); +bool crcc37d_ctx_finished(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx); + +#endif /* !__CRCC37D_H__ */ diff --git a/drivers/gpu/drm/nouveau/dispnv50/crcc57d.c b/drivers/gpu/drm/nouveau/dispnv50/crcc57d.c new file mode 100644 index 000000000000..cc0130e3d496 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/crcc57d.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT + +#include "crc.h" +#include "crcc37d.h" +#include "core.h" +#include "disp.h" +#include "head.h" + +#include <nvif/pushc37b.h> + +#include <nvhw/class/clc57d.h> + +static int crcc57d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source, + struct nv50_crc_notifier_ctx *ctx) +{ + struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + const int i = head->base.index; + u32 crc_args = NVDEF(NVC57D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, CORE) | + NVDEF(NVC57D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) | + NVDEF(NVC57D, HEAD_SET_CRC_CONTROL, SECONDARY_CRC, NONE) | + NVDEF(NVC57D, HEAD_SET_CRC_CONTROL, CRC_DURING_SNOOZE, DISABLE); + int ret; + + switch (source) { + case NV50_CRC_SOURCE_TYPE_SOR: + crc_args |= NVDEF(NVC57D, HEAD_SET_CRC_CONTROL, PRIMARY_CRC, SOR(or)); + break; + case NV50_CRC_SOURCE_TYPE_SF: + crc_args |= NVDEF(NVC57D, HEAD_SET_CRC_CONTROL, PRIMARY_CRC, SF); + break; + default: + break; + } + + ret = PUSH_WAIT(push, 4); + if (ret) + return ret; + + if (source) { + PUSH_MTHD(push, NVC57D, HEAD_SET_CONTEXT_DMA_CRC(i), ctx->ntfy.handle); + PUSH_MTHD(push, NVC57D, HEAD_SET_CRC_CONTROL(i), crc_args); + } else { + PUSH_MTHD(push, NVC57D, HEAD_SET_CRC_CONTROL(i), 0); + PUSH_MTHD(push, NVC57D, HEAD_SET_CONTEXT_DMA_CRC(i), 0); + } + + return 0; +} + +const struct nv50_crc_func crcc57d = { + .set_src = crcc57d_set_src, + .set_ctx = crcc37d_set_ctx, + .get_entry = crcc37d_get_entry, + .ctx_finished = crcc37d_ctx_finished, + .flip_threshold = CRCC37D_FLIP_THRESHOLD, + .num_entries = CRCC37D_MAX_ENTRIES, + .notifier_len = sizeof(struct crcc37d_notifier), +}; diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c index 54fbd6fe751d..00e19fd959ea 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c +++ b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c @@ -98,6 +98,7 @@ static int curs507a_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, struct nv50_head_atom *asyh) { + struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev); struct nv50_head *head = nv50_head(asyw->state.crtc); int ret; @@ -109,8 +110,20 @@ curs507a_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, if (ret || !asyh->curs.visible) return ret; - if (asyw->image.w != asyw->image.h) + if (asyw->state.crtc_w != asyw->state.crtc_h) { + NV_ATOMIC(drm, "Plane width/height must be equal for cursors\n"); return -EINVAL; + } + + if (asyw->image.w != asyw->state.crtc_w) { + NV_ATOMIC(drm, "Plane width must be equal to fb width for cursors (height can be larger though)\n"); + return -EINVAL; + } + + if (asyw->state.src_x || asyw->state.src_y) { + NV_ATOMIC(drm, "Cursor planes do not support framebuffer offsets\n"); + return -EINVAL; + } ret = head->func->curs_layout(head, asyw, asyh); if (ret) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 8e28403ea9b1..ae1f41205520 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -852,6 +852,9 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc, ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, &nv_connector->base, mode); if (!ret) { + drm_hdmi_avi_infoframe_quant_range(&avi_frame.avi, + &nv_connector->base, mode, + HDMI_QUANTIZATION_RANGE_FULL); /* We have an AVI InfoFrame, populate it to the display */ args.pwr.avi_infoframe_length = hdmi_infoframe_pack(&avi_frame, args.infoframes, 17); @@ -1387,12 +1390,11 @@ nv50_mstm_cleanup(struct nv50_mstm *mstm) { struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev); struct drm_encoder *encoder; - int ret; NV_ATOMIC(drm, "%s: mstm cleanup\n", mstm->outp->base.base.name); - ret = drm_dp_check_act_status(&mstm->mgr); + drm_dp_check_act_status(&mstm->mgr); - ret = drm_dp_update_payload_part2(&mstm->mgr); + drm_dp_update_payload_part2(&mstm->mgr); drm_for_each_encoder(encoder, mstm->outp->base.base.dev) { if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) { @@ -1411,10 +1413,9 @@ nv50_mstm_prepare(struct nv50_mstm *mstm) { struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev); struct drm_encoder *encoder; - int ret; NV_ATOMIC(drm, "%s: mstm prepare\n", mstm->outp->base.base.name); - ret = drm_dp_update_payload_part1(&mstm->mgr, 1); + drm_dp_update_payload_part1(&mstm->mgr, 1); drm_for_each_encoder(encoder, mstm->outp->base.base.dev) { if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index 72099d1e4816..c3c57be54e1c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -226,10 +226,24 @@ static int nv50_head_atomic_check_lut(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nv50_disp *disp = nv50_disp(head->base.base.dev); - struct drm_property_blob *olut = asyh->state.gamma_lut; + struct drm_device *dev = head->base.base.dev; + struct drm_crtc *crtc = &head->base.base; + struct nv50_disp *disp = nv50_disp(dev); + struct nouveau_drm *drm = nouveau_drm(dev); + struct drm_property_blob *olut = asyh->state.gamma_lut, + *ilut = asyh->state.degamma_lut; int size; + /* Ensure that the ilut is valid */ + if (ilut) { + size = drm_color_lut_size(ilut); + if (!head->func->ilut_check(size)) { + NV_ATOMIC(drm, "Invalid size %d for degamma on [CRTC:%d:%s]\n", + size, crtc->base.id, crtc->name); + return -EINVAL; + } + } + /* Determine whether core output LUT should be enabled. */ if (olut) { /* Check if any window(s) have stolen the core output LUT @@ -256,7 +270,8 @@ nv50_head_atomic_check_lut(struct nv50_head *head, } if (!head->func->olut(head, asyh, size)) { - DRM_DEBUG_KMS("Invalid olut\n"); + NV_ATOMIC(drm, "Invalid size %d for gamma on [CRTC:%d:%s]\n", + size, crtc->base.id, crtc->name); return -EINVAL; } asyh->olut.handle = disp->core->chan.vram.handle; @@ -330,8 +345,17 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) struct drm_connector_state *conns; struct drm_connector *conn; int i, ret; + bool check_lut = asyh->state.color_mgmt_changed || + memcmp(&armh->wndw, &asyh->wndw, sizeof(asyh->wndw)); NV_ATOMIC(drm, "%s atomic_check %d\n", crtc->name, asyh->state.active); + + if (check_lut) { + ret = nv50_head_atomic_check_lut(head, asyh); + if (ret) + return ret; + } + if (asyh->state.active) { for_each_new_connector_in_state(asyh->state.state, conn, conns, i) { if (conns->crtc == crtc) { @@ -357,14 +381,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) if (asyh->state.mode_changed || asyh->state.connectors_changed) nv50_head_atomic_check_mode(head, asyh); - if (asyh->state.color_mgmt_changed || - memcmp(&armh->wndw, &asyh->wndw, sizeof(asyh->wndw))) { - int ret = nv50_head_atomic_check_lut(head, asyh); - if (ret) - return ret; - + if (check_lut) asyh->olut.visible = asyh->olut.handle != 0; - } if (asyc) { if (asyc->set.scaler) diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.h b/drivers/gpu/drm/nouveau/dispnv50/head.h index 0bac6be9ba34..41c8788dfb31 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.h +++ b/drivers/gpu/drm/nouveau/dispnv50/head.h @@ -29,6 +29,7 @@ struct nv50_head_func { int (*view)(struct nv50_head *, struct nv50_head_atom *); int (*mode)(struct nv50_head *, struct nv50_head_atom *); bool (*olut)(struct nv50_head *, struct nv50_head_atom *, int); + bool (*ilut_check)(int size); bool olut_identity; int olut_size; int (*olut_set)(struct nv50_head *, struct nv50_head_atom *); @@ -71,6 +72,7 @@ extern const struct nv50_head_func head907d; int head907d_view(struct nv50_head *, struct nv50_head_atom *); int head907d_mode(struct nv50_head *, struct nv50_head_atom *); bool head907d_olut(struct nv50_head *, struct nv50_head_atom *, int); +bool head907d_ilut_check(int size); int head907d_olut_set(struct nv50_head *, struct nv50_head_atom *); int head907d_olut_clr(struct nv50_head *); int head907d_core_set(struct nv50_head *, struct nv50_head_atom *); diff --git a/drivers/gpu/drm/nouveau/dispnv50/head907d.c b/drivers/gpu/drm/nouveau/dispnv50/head907d.c index 85648d790743..18fe4c1e2d6a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head907d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head907d.c @@ -314,6 +314,11 @@ head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) return true; } +bool head907d_ilut_check(int size) +{ + return size == 256 || size == 1024; +} + int head907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) { @@ -409,6 +414,7 @@ head907d = { .view = head907d_view, .mode = head907d_mode, .olut = head907d_olut, + .ilut_check = head907d_ilut_check, .olut_size = 1024, .olut_set = head907d_olut_set, .olut_clr = head907d_olut_clr, diff --git a/drivers/gpu/drm/nouveau/dispnv50/head917d.c b/drivers/gpu/drm/nouveau/dispnv50/head917d.c index ea9f8667305e..4ce47b55f72c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head917d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head917d.c @@ -119,6 +119,7 @@ head917d = { .view = head907d_view, .mode = head907d_mode, .olut = head907d_olut, + .ilut_check = head907d_ilut_check, .olut_size = 1024, .olut_set = head907d_olut_set, .olut_clr = head907d_olut_clr, diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c index 63adfeba50e5..a4a3b78ea42c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c @@ -285,6 +285,7 @@ headc37d = { .view = headc37d_view, .mode = headc37d_mode, .olut = headc37d_olut, + .ilut_check = head907d_ilut_check, .olut_size = 1024, .olut_set = headc37d_olut_set, .olut_clr = headc37d_olut_clr, diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c index fd51527b56b8..543f08ceaad6 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c @@ -169,7 +169,7 @@ headc57d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem) writew(readw(mem - 4), mem + 4); } -bool +static bool headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) { if (size != 0 && size != 256 && size != 1024) @@ -236,6 +236,7 @@ headc57d = { .view = headc37d_view, .mode = headc57d_mode, .olut = headc57d_olut, + .ilut_check = head907d_ilut_check, .olut_identity = true, .olut_size = 1024, .olut_set = headc57d_olut_set, diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 8d048bacd6f0..133c8736426a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -403,10 +403,7 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, /* Recalculate LUT state. */ memset(&asyw->xlut, 0x00, sizeof(asyw->xlut)); if ((asyw->ilut = wndw->func->ilut ? ilut : NULL)) { - if (!wndw->func->ilut(wndw, asyw, drm_color_lut_size(ilut))) { - DRM_DEBUG_KMS("Invalid ilut\n"); - return -EINVAL; - } + wndw->func->ilut(wndw, asyw, drm_color_lut_size(ilut)); asyw->xlut.handle = wndw->wndw.vram.handle; asyw->xlut.i.buffer = !asyw->xlut.i.buffer; asyw->set.xlut = true; @@ -539,6 +536,8 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) struct nouveau_bo *nvbo; struct nv50_head_atom *asyh; struct nv50_wndw_ctxdma *ctxdma; + struct dma_resv_iter cursor; + struct dma_fence *fence; int ret; NV_ATOMIC(drm, "%s prepare: %p\n", plane->name, fb); @@ -561,7 +560,13 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) asyw->image.handle[0] = ctxdma->object.handle; } - asyw->state.fence = dma_resv_get_excl_unlocked(nvbo->bo.base.resv); + dma_resv_iter_begin(&cursor, nvbo->bo.base.resv, false); + dma_resv_for_each_fence_unlocked(&cursor, fence) { + /* TODO: We only use the first writer here */ + asyw->state.fence = dma_fence_get(fence); + break; + } + dma_resv_iter_end(&cursor); asyw->image.offset[0] = nvbo->offset; if (wndw->func->prepare) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index f4e0c5080034..9c9f2c2a71a5 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -64,7 +64,7 @@ struct nv50_wndw_func { int (*ntfy_clr)(struct nv50_wndw *); int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset, struct nvif_device *); - bool (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *, int); + void (*ilut)(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyh, int size); void (*csc)(struct nv50_wndw *, struct nv50_wndw_atom *, const struct drm_color_ctm *); int (*csc_set)(struct nv50_wndw *, struct nv50_wndw_atom *); @@ -129,7 +129,7 @@ int wndwc37e_update(struct nv50_wndw *, u32 *); int wndwc57e_new(struct nouveau_drm *, enum drm_plane_type, int, s32, struct nv50_wndw **); -bool wndwc57e_ilut(struct nv50_wndw *, struct nv50_wndw_atom *, int); +void wndwc57e_ilut(struct nv50_wndw *, struct nv50_wndw_atom *, int); int wndwc57e_ilut_set(struct nv50_wndw *, struct nv50_wndw_atom *); int wndwc57e_ilut_clr(struct nv50_wndw *); int wndwc57e_csc_set(struct nv50_wndw *, struct nv50_wndw_atom *); diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c index 57df997c5ff3..183d2c0e65b6 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c @@ -82,18 +82,14 @@ wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) return 0; } -static bool +static void wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) { - if (size != 256 && size != 1024) - return false; - asyw->xlut.i.size = size == 1024 ? NVC37E_SET_CONTROL_INPUT_LUT_SIZE_SIZE_1025 : NVC37E_SET_CONTROL_INPUT_LUT_SIZE_SIZE_257; asyw->xlut.i.range = NVC37E_SET_CONTROL_INPUT_LUT_RANGE_UNITY; asyw->xlut.i.output_mode = NVC37E_SET_CONTROL_INPUT_LUT_OUTPUT_MODE_INTERPOLATE; asyw->xlut.i.load = head907d_olut_load; - return true; } int diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c index abdd3bb658b3..37f6da8b3f2a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c @@ -179,11 +179,11 @@ wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem) writew(readw(mem - 4), mem + 4); } -bool +void wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) { - if (size = size ? size : 1024, size != 256 && size != 1024) - return false; + if (!size) + size = 1024; if (size == 256) asyw->xlut.i.mode = NVC57E_SET_ILUT_CONTROL_MODE_DIRECT8; @@ -193,7 +193,6 @@ wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) asyw->xlut.i.size = 4 /* VSS header. */ + size + 1 /* Entries. */; asyw->xlut.i.output_mode = NVC57E_SET_ILUT_CONTROL_INTERPOLATE_DISABLE; asyw->xlut.i.load = wndwc57e_ilut_load; - return true; } /**************************************************************** diff --git a/drivers/gpu/drm/nouveau/include/nvhw/class/cl907d.h b/drivers/gpu/drm/nouveau/include/nvhw/class/cl907d.h index 79aff6ff3138..f972ef1409f4 100644 --- a/drivers/gpu/drm/nouveau/include/nvhw/class/cl907d.h +++ b/drivers/gpu/drm/nouveau/include/nvhw/class/cl907d.h @@ -246,6 +246,9 @@ #define NV907D_HEAD_SET_CRC_CONTROL_CRC_DURING_SNOOZE 5:5 #define NV907D_HEAD_SET_CRC_CONTROL_CRC_DURING_SNOOZE_DISABLE (0x00000000) #define NV907D_HEAD_SET_CRC_CONTROL_CRC_DURING_SNOOZE_ENABLE (0x00000001) +#define NV907D_HEAD_SET_CRC_CONTROL_WIDE_PIPE_CRC 6:6 +#define NV907D_HEAD_SET_CRC_CONTROL_WIDE_PIPE_CRC_DISABLE (0x00000000) +#define NV907D_HEAD_SET_CRC_CONTROL_WIDE_PIPE_CRC_ENABLE (0x00000001) #define NV907D_HEAD_SET_CONTEXT_DMA_CRC(a) (0x00000438 + (a)*0x00000300) #define NV907D_HEAD_SET_CONTEXT_DMA_CRC_HANDLE 31:0 #define NV907D_HEAD_SET_OUTPUT_LUT_LO(a) (0x00000448 + (a)*0x00000300) diff --git a/drivers/gpu/drm/nouveau/include/nvhw/class/clc57d.h b/drivers/gpu/drm/nouveau/include/nvhw/class/clc57d.h index d83ac815e06c..d4bad2da3e56 100644 --- a/drivers/gpu/drm/nouveau/include/nvhw/class/clc57d.h +++ b/drivers/gpu/drm/nouveau/include/nvhw/class/clc57d.h @@ -265,6 +265,75 @@ #define NVC57D_HEAD_SET_RASTER_BLANK_START(a) (0x00002070 + (a)*0x00000400) #define NVC57D_HEAD_SET_RASTER_BLANK_START_X 14:0 #define NVC57D_HEAD_SET_RASTER_BLANK_START_Y 30:16 +#define NVC57D_HEAD_SET_CONTEXT_DMA_CRC(a) (0x00002180 + (a)*0x00000400) +#define NVC57D_HEAD_SET_CONTEXT_DMA_CRC_HANDLE 31:0 +#define NVC57D_HEAD_SET_CRC_CONTROL(a) (0x00002184 + (a)*0x00000400) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL 5:0 +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_0 (0x00000000) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_1 (0x00000001) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_2 (0x00000002) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_3 (0x00000003) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_4 (0x00000004) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_5 (0x00000005) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_6 (0x00000006) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_7 (0x00000007) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_8 (0x00000008) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_9 (0x00000009) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_10 (0x0000000A) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_11 (0x0000000B) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_12 (0x0000000C) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_13 (0x0000000D) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_14 (0x0000000E) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_15 (0x0000000F) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_16 (0x00000010) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_17 (0x00000011) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_18 (0x00000012) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_19 (0x00000013) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_20 (0x00000014) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_21 (0x00000015) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_22 (0x00000016) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_23 (0x00000017) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_24 (0x00000018) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_25 (0x00000019) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_26 (0x0000001A) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_27 (0x0000001B) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_28 (0x0000001C) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_29 (0x0000001D) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_30 (0x0000001E) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_WIN_31 (0x0000001F) +#define NVC57D_HEAD_SET_CRC_CONTROL_CONTROLLING_CHANNEL_CORE (0x00000020) +#define NVC57D_HEAD_SET_CRC_CONTROL_EXPECT_BUFFER_COLLAPSE 8:8 +#define NVC57D_HEAD_SET_CRC_CONTROL_EXPECT_BUFFER_COLLAPSE_FALSE (0x00000000) +#define NVC57D_HEAD_SET_CRC_CONTROL_EXPECT_BUFFER_COLLAPSE_TRUE (0x00000001) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC 19:12 +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_NONE (0x00000000) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SF (0x00000030) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR(i) (0x00000050 +(i)) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR__SIZE_1 8 +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR0 (0x00000050) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR1 (0x00000051) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR2 (0x00000052) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR3 (0x00000053) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR4 (0x00000054) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR5 (0x00000055) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR6 (0x00000056) +#define NVC57D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR7 (0x00000057) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC 27:20 +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_NONE (0x00000000) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SF (0x00000030) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR(i) (0x00000050 +(i)) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR__SIZE_1 8 +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR0 (0x00000050) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR1 (0x00000051) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR2 (0x00000052) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR3 (0x00000053) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR4 (0x00000054) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR5 (0x00000055) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR6 (0x00000056) +#define NVC57D_HEAD_SET_CRC_CONTROL_SECONDARY_CRC_SOR7 (0x00000057) +#define NVC57D_HEAD_SET_CRC_CONTROL_CRC_DURING_SNOOZE 9:9 +#define NVC57D_HEAD_SET_CRC_CONTROL_CRC_DURING_SNOOZE_DISABLE (0x00000000) +#define NVC57D_HEAD_SET_CRC_CONTROL_CRC_DURING_SNOOZE_ENABLE (0x00000001) #define NVC57D_HEAD_SET_OLUT_CONTROL(a) (0x00002280 + (a)*0x00000400) #define NVC57D_HEAD_SET_OLUT_CONTROL_INTERPOLATE 0:0 #define NVC57D_HEAD_SET_OLUT_CONTROL_INTERPOLATE_DISABLE (0x00000000) diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 1cbd71abc80a..ae2f2abc8f5a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -308,7 +308,10 @@ nv50_backlight_init(struct nouveau_backlight *bl, if (ret < 0) return ret; - if (drm_edp_backlight_supported(edp_dpcd)) { + /* TODO: Add support for hybrid PWM/DPCD panels */ + if (drm_edp_backlight_supported(edp_dpcd) && + (edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && + (edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) { NV_DEBUG(drm, "DPCD backlight controls supported on %s\n", nv_conn->base.name); diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index e8c445eb1100..41b78e9ecd4e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -2045,7 +2045,6 @@ nouveau_run_vbios_init(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; - int ret = 0; /* Reset the BIOS head to 0. */ bios->state.crtchead = 0; @@ -2058,7 +2057,7 @@ nouveau_run_vbios_init(struct drm_device *dev) bios->fp.lvds_init_run = false; } - return ret; + return 0; } static bool diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 929de41c281f..2b460835a438 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -306,7 +306,7 @@ nouveau_framebuffer_new(struct drm_device *dev, struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct drm_framebuffer *fb; const struct drm_format_info *info; - unsigned int width, height, i; + unsigned int height, i; uint32_t tile_mode; uint8_t kind; int ret; @@ -343,9 +343,6 @@ nouveau_framebuffer_new(struct drm_device *dev, info = drm_get_format_info(dev, mode_cmd); for (i = 0; i < info->num_planes; i++) { - width = drm_format_info_plane_width(info, - mode_cmd->width, - i); height = drm_format_info_plane_height(info, mode_cmd->height, i); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 05d0b3eb3690..26f9299df881 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -339,14 +339,15 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) } int -nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool exclusive, bool intr) +nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, + bool exclusive, bool intr) { struct nouveau_fence_chan *fctx = chan->fence; - struct dma_fence *fence; struct dma_resv *resv = nvbo->bo.base.resv; - struct dma_resv_list *fobj; + struct dma_resv_iter cursor; + struct dma_fence *fence; struct nouveau_fence *f; - int ret = 0, i; + int ret; if (!exclusive) { ret = dma_resv_reserve_shared(resv, 1); @@ -355,10 +356,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e return ret; } - fobj = dma_resv_shared_list(resv); - fence = dma_resv_excl_fence(resv); - - if (fence) { + dma_resv_for_each_fence(&cursor, resv, exclusive, fence) { struct nouveau_channel *prev = NULL; bool must_wait = true; @@ -366,41 +364,19 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e if (f) { rcu_read_lock(); prev = rcu_dereference(f->channel); - if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0)) + if (prev && (prev == chan || + fctx->sync(f, prev, chan) == 0)) must_wait = false; rcu_read_unlock(); } - if (must_wait) + if (must_wait) { ret = dma_fence_wait(fence, intr); - - return ret; - } - - if (!exclusive || !fobj) - return ret; - - for (i = 0; i < fobj->shared_count && !ret; ++i) { - struct nouveau_channel *prev = NULL; - bool must_wait = true; - - fence = rcu_dereference_protected(fobj->shared[i], - dma_resv_held(resv)); - - f = nouveau_local_fence(fence, chan->drm); - if (f) { - rcu_read_lock(); - prev = rcu_dereference(f->channel); - if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0)) - must_wait = false; - rcu_read_unlock(); + if (ret) + return ret; } - - if (must_wait) - ret = dma_fence_wait(fence, intr); } - - return ret; + return 0; } void diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index ac671202919e..0c8c55c73b12 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -60,7 +60,7 @@ nvkm_uclient_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, return 0; } -const struct nvkm_sclass +static const struct nvkm_sclass nvkm_uclient_sclass = { .oclass = NVIF_CLASS_CLIENT, .minver = 0, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c index f28894fdede9..113ddc103ac2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c @@ -161,8 +161,8 @@ nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size) if (imem && args->v0.ram_size > 0) args->v0.ram_user = args->v0.ram_user - imem->reserved; - strncpy(args->v0.chip, device->chip->name, sizeof(args->v0.chip)); - strncpy(args->v0.name, device->name, sizeof(args->v0.name)); + snprintf(args->v0.chip, sizeof(args->v0.chip), "%s", device->chip->name); + snprintf(args->v0.name, sizeof(args->v0.name), "%s", device->name); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c index e20a48f201f6..448a515057c7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c @@ -106,6 +106,8 @@ gv100_disp_core_mthd_head = { { 0x20a4, 0x6820a4 }, { 0x20a8, 0x6820a8 }, { 0x20ac, 0x6820ac }, + { 0x2180, 0x682180 }, + { 0x2184, 0x682184 }, { 0x218c, 0x68218c }, { 0x2194, 0x682194 }, { 0x2198, 0x682198 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c index e417044cc347..260b197f81bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c @@ -49,7 +49,7 @@ tu102_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, /*XXX: how to wait? can you even wait? */ } -const struct gk104_fifo_runlist_func +static const struct gk104_fifo_runlist_func tu102_fifo_runlist = { .size = 16, .cgrp = gv100_fifo_runlist_cgrp, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index 262641a014b0..c91130a6be2a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -117,8 +117,12 @@ nvkm_falcon_disable(struct nvkm_falcon *falcon) int nvkm_falcon_reset(struct nvkm_falcon *falcon) { - nvkm_falcon_disable(falcon); - return nvkm_falcon_enable(falcon); + if (!falcon->func->reset) { + nvkm_falcon_disable(falcon); + return nvkm_falcon_enable(falcon); + } + + return falcon->func->reset(falcon); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index 9de74f41dcd2..142079403864 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -401,7 +401,7 @@ init_table_(struct nvbios_init *init, u16 offset, const char *name) #define init_macro_table(b) init_table_((b), 0x04, "macro table") #define init_condition_table(b) init_table_((b), 0x06, "condition table") #define init_io_condition_table(b) init_table_((b), 0x08, "io condition table") -#define init_io_flag_condition_table(b) init_table_((b), 0x0a, "io flag conditon table") +#define init_io_flag_condition_table(b) init_table_((b), 0x0a, "io flag condition table") #define init_function_table(b) init_table_((b), 0x0c, "function table") #define init_xlat_table(b) init_table_((b), 0x10, "xlat table"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c index fb90d47e1225..a9cdf2411187 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c @@ -32,7 +32,6 @@ mcp89_devinit_disable(struct nvkm_devinit *init) struct nvkm_device *device = init->subdev.device; u32 r001540 = nvkm_rd32(device, 0x001540); u32 r00154c = nvkm_rd32(device, 0x00154c); - u64 disable = 0; if (!(r001540 & 0x40000000)) { nvkm_subdev_disable(device, NVKM_ENGINE_MSPDEC, 0); @@ -48,7 +47,7 @@ mcp89_devinit_disable(struct nvkm_devinit *init) if (!(r00154c & 0x00000200)) nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); - return disable; + return 0; } static const struct nvkm_devinit_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 24382875fb4f..455e95a89259 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -94,20 +94,13 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) return 0; } -static int +static void nvkm_pmu_reset(struct nvkm_pmu *pmu) { struct nvkm_device *device = pmu->subdev.device; if (!pmu->func->enabled(pmu)) - return 0; - - /* Inhibit interrupts, and wait for idle. */ - nvkm_wr32(device, 0x10a014, 0x0000ffff); - nvkm_msec(device, 2000, - if (!nvkm_rd32(device, 0x10a04c)) - break; - ); + return; /* Reset. */ if (pmu->func->reset) @@ -118,25 +111,37 @@ nvkm_pmu_reset(struct nvkm_pmu *pmu) if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006)) break; ); - - return 0; } static int nvkm_pmu_preinit(struct nvkm_subdev *subdev) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); - return nvkm_pmu_reset(pmu); + nvkm_pmu_reset(pmu); + return 0; } static int nvkm_pmu_init(struct nvkm_subdev *subdev) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); - int ret = nvkm_pmu_reset(pmu); - if (ret == 0 && pmu->func->init) - ret = pmu->func->init(pmu); - return ret; + struct nvkm_device *device = pmu->subdev.device; + + if (!pmu->func->init) + return 0; + + if (pmu->func->enabled(pmu)) { + /* Inhibit interrupts, and wait for idle. */ + nvkm_wr32(device, 0x10a014, 0x0000ffff); + nvkm_msec(device, 2000, + if (!nvkm_rd32(device, 0x10a04c)) + break; + ); + + nvkm_pmu_reset(pmu); + } + + return pmu->func->init(pmu); } static void * diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c index 5968c7696596..40439e329aa9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c @@ -23,9 +23,38 @@ */ #include "priv.h" +static int +gm200_pmu_flcn_reset(struct nvkm_falcon *falcon) +{ + struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon); + + nvkm_falcon_wr32(falcon, 0x014, 0x0000ffff); + pmu->func->reset(pmu); + return nvkm_falcon_enable(falcon); +} + +const struct nvkm_falcon_func +gm200_pmu_flcn = { + .debug = 0xc08, + .fbif = 0xe00, + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, + .reset = gm200_pmu_flcn_reset, + .cmdq = { 0x4a0, 0x4b0, 4 }, + .msgq = { 0x4c8, 0x4cc, 0 }, +}; + static const struct nvkm_pmu_func gm200_pmu = { - .flcn = >215_pmu_flcn, + .flcn = &gm200_pmu_flcn, .enabled = gf100_pmu_enabled, .reset = gf100_pmu_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 148706977eec..e1772211b0a4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -211,7 +211,7 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu) static const struct nvkm_pmu_func gm20b_pmu = { - .flcn = >215_pmu_flcn, + .flcn = &gm200_pmu_flcn, .enabled = gf100_pmu_enabled, .intr = gt215_pmu_intr, .recv = gm20b_pmu_recv, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c index 00da1b873ce8..6bf7fc1bd1e3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c @@ -39,7 +39,7 @@ gp102_pmu_enabled(struct nvkm_pmu *pmu) static const struct nvkm_pmu_func gp102_pmu = { - .flcn = >215_pmu_flcn, + .flcn = &gm200_pmu_flcn, .enabled = gp102_pmu_enabled, .reset = gp102_pmu_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index 461f722656e2..ba1583bb618b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -78,7 +78,7 @@ gp10b_pmu_acr = { static const struct nvkm_pmu_func gp10b_pmu = { - .flcn = >215_pmu_flcn, + .flcn = &gm200_pmu_flcn, .enabled = gf100_pmu_enabled, .intr = gt215_pmu_intr, .recv = gm20b_pmu_recv, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index e7860d177353..bcaade758ff7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -44,6 +44,8 @@ void gf100_pmu_reset(struct nvkm_pmu *); void gk110_pmu_pgob(struct nvkm_pmu *, bool); +extern const struct nvkm_falcon_func gm200_pmu_flcn; + void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64); void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); int gm20b_pmu_acr_boot(struct nvkm_falcon *); |