Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: MIT |
| 2 | #include <drm/drm_crtc.h> |
| 3 | |
| 4 | #include "crc.h" |
Lyude Paul | 57cbdbe | 2021-01-18 20:48:47 -0500 | [diff] [blame] | 5 | #include "crcc37d.h" |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 6 | #include "core.h" |
| 7 | #include "disp.h" |
| 8 | #include "head.h" |
| 9 | |
Lyude Paul | a255e9c | 2020-08-10 17:18:37 -0400 | [diff] [blame] | 10 | #include <nvif/pushc37b.h> |
Ben Skeggs | c4b27bc | 2020-07-18 17:39:15 +1000 | [diff] [blame] | 11 | |
Ben Skeggs | 6162638 | 2020-07-20 07:56:31 +1000 | [diff] [blame] | 12 | #include <nvhw/class/clc37d.h> |
| 13 | |
Ben Skeggs | c4b27bc | 2020-07-18 17:39:15 +1000 | [diff] [blame] | 14 | static int |
Lyude Paul | 57cbdbe | 2021-01-18 20:48:47 -0500 | [diff] [blame] | 15 | crcc37d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source, |
| 16 | struct nv50_crc_notifier_ctx *ctx) |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 17 | { |
Ben Skeggs | c4b27bc | 2020-07-18 17:39:15 +1000 | [diff] [blame] | 18 | struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; |
| 19 | const int i = head->base.index; |
Lyude Paul | 57cbdbe | 2021-01-18 20:48:47 -0500 | [diff] [blame] | 20 | u32 crc_args = NVVAL(NVC37D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, i * 4) | |
Ben Skeggs | 6162638 | 2020-07-20 07:56:31 +1000 | [diff] [blame] | 21 | NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) | |
| 22 | NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, SECONDARY_CRC, NONE) | |
| 23 | NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, CRC_DURING_SNOOZE, DISABLE); |
Ben Skeggs | c4b27bc | 2020-07-18 17:39:15 +1000 | [diff] [blame] | 24 | int ret; |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 25 | |
| 26 | switch (source) { |
| 27 | case NV50_CRC_SOURCE_TYPE_SOR: |
Ben Skeggs | 6162638 | 2020-07-20 07:56:31 +1000 | [diff] [blame] | 28 | crc_args |= NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, PRIMARY_CRC, SOR(or)); |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 29 | break; |
| 30 | case NV50_CRC_SOURCE_TYPE_PIOR: |
Ben Skeggs | 6162638 | 2020-07-20 07:56:31 +1000 | [diff] [blame] | 31 | crc_args |= NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, PRIMARY_CRC, PIOR(or)); |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 32 | break; |
| 33 | case NV50_CRC_SOURCE_TYPE_SF: |
Ben Skeggs | 6162638 | 2020-07-20 07:56:31 +1000 | [diff] [blame] | 34 | crc_args |= NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, PRIMARY_CRC, SF); |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 35 | break; |
| 36 | default: |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 37 | break; |
| 38 | } |
| 39 | |
Ben Skeggs | c4b27bc | 2020-07-18 17:39:15 +1000 | [diff] [blame] | 40 | if ((ret = PUSH_WAIT(push, 4))) |
| 41 | return ret; |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 42 | |
| 43 | if (source) { |
Ben Skeggs | 6162638 | 2020-07-20 07:56:31 +1000 | [diff] [blame] | 44 | PUSH_MTHD(push, NVC37D, HEAD_SET_CONTEXT_DMA_CRC(i), ctx->ntfy.handle); |
| 45 | PUSH_MTHD(push, NVC37D, HEAD_SET_CRC_CONTROL(i), crc_args); |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 46 | } else { |
Ben Skeggs | 6162638 | 2020-07-20 07:56:31 +1000 | [diff] [blame] | 47 | PUSH_MTHD(push, NVC37D, HEAD_SET_CRC_CONTROL(i), 0); |
| 48 | PUSH_MTHD(push, NVC37D, HEAD_SET_CONTEXT_DMA_CRC(i), 0); |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 49 | } |
| 50 | |
Ben Skeggs | c4b27bc | 2020-07-18 17:39:15 +1000 | [diff] [blame] | 51 | return 0; |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 52 | } |
| 53 | |
Lyude Paul | 57cbdbe | 2021-01-18 20:48:47 -0500 | [diff] [blame] | 54 | int crcc37d_set_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx) |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 55 | { |
Ben Skeggs | ae09163 | 2020-07-18 17:42:27 +1000 | [diff] [blame] | 56 | struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; |
| 57 | const int i = head->base.index; |
| 58 | int ret; |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 59 | |
Ben Skeggs | ae09163 | 2020-07-18 17:42:27 +1000 | [diff] [blame] | 60 | if ((ret = PUSH_WAIT(push, 2))) |
| 61 | return ret; |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 62 | |
Ben Skeggs | 1fad04c | 2020-07-20 09:49:39 +1000 | [diff] [blame] | 63 | PUSH_MTHD(push, NVC37D, HEAD_SET_CONTEXT_DMA_CRC(i), ctx ? ctx->ntfy.handle : 0); |
Ben Skeggs | ae09163 | 2020-07-18 17:42:27 +1000 | [diff] [blame] | 64 | return 0; |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 65 | } |
| 66 | |
Lyude Paul | 57cbdbe | 2021-01-18 20:48:47 -0500 | [diff] [blame] | 67 | u32 crcc37d_get_entry(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx, |
| 68 | enum nv50_crc_source source, int idx) |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 69 | { |
| 70 | struct crcc37d_notifier __iomem *notifier = ctx->mem.object.map.ptr; |
| 71 | struct crcc37d_entry __iomem *entry = ¬ifier->entries[idx]; |
| 72 | u32 __iomem *crc_addr; |
| 73 | |
| 74 | if (source == NV50_CRC_SOURCE_RG) |
| 75 | crc_addr = &entry->rg_crc; |
| 76 | else |
| 77 | crc_addr = &entry->output_crc[0]; |
| 78 | |
| 79 | return ioread32_native(crc_addr); |
| 80 | } |
| 81 | |
Lyude Paul | 57cbdbe | 2021-01-18 20:48:47 -0500 | [diff] [blame] | 82 | bool crcc37d_ctx_finished(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx) |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 83 | { |
| 84 | struct nouveau_drm *drm = nouveau_drm(head->base.base.dev); |
| 85 | struct crcc37d_notifier __iomem *notifier = ctx->mem.object.map.ptr; |
| 86 | const u32 status = ioread32_native(¬ifier->status); |
| 87 | const u32 overflow = status & 0x0000007e; |
| 88 | |
| 89 | if (!(status & 0x00000001)) |
| 90 | return false; |
| 91 | |
| 92 | if (overflow) { |
| 93 | const char *engine = NULL; |
| 94 | |
| 95 | switch (overflow) { |
| 96 | case 0x00000004: engine = "Front End"; break; |
| 97 | case 0x00000008: engine = "Compositor"; break; |
| 98 | case 0x00000010: engine = "RG"; break; |
| 99 | case 0x00000020: engine = "CRC output 1"; break; |
| 100 | case 0x00000040: engine = "CRC output 2"; break; |
| 101 | } |
| 102 | |
| 103 | if (engine) |
| 104 | NV_ERROR(drm, |
| 105 | "CRC notifier context for head %d overflowed on %s: %x\n", |
| 106 | head->base.index, engine, status); |
| 107 | else |
| 108 | NV_ERROR(drm, |
| 109 | "CRC notifier context for head %d overflowed: %x\n", |
| 110 | head->base.index, status); |
| 111 | } |
| 112 | |
| 113 | NV_DEBUG(drm, "Head %d CRC context status: %x\n", |
| 114 | head->base.index, status); |
| 115 | |
| 116 | return true; |
| 117 | } |
| 118 | |
| 119 | const struct nv50_crc_func crcc37d = { |
| 120 | .set_src = crcc37d_set_src, |
| 121 | .set_ctx = crcc37d_set_ctx, |
| 122 | .get_entry = crcc37d_get_entry, |
| 123 | .ctx_finished = crcc37d_ctx_finished, |
Lyude Paul | 57cbdbe | 2021-01-18 20:48:47 -0500 | [diff] [blame] | 124 | .flip_threshold = CRCC37D_FLIP_THRESHOLD, |
Lyude Paul | 12885ec | 2019-10-07 14:20:12 -0400 | [diff] [blame] | 125 | .num_entries = CRCC37D_MAX_ENTRIES, |
| 126 | .notifier_len = sizeof(struct crcc37d_notifier), |
| 127 | }; |