Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 1 | #ifndef __NVKM_FBRAM_FUC_H__ |
| 2 | #define __NVKM_FBRAM_FUC_H__ |
Ben Skeggs | 6758745 | 2015-08-20 14:54:09 +1000 | [diff] [blame] | 3 | #include <subdev/fb.h> |
Ben Skeggs | ebb58dc | 2015-01-14 00:04:21 +1000 | [diff] [blame] | 4 | #include <subdev/pmu.h> |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 5 | |
| 6 | struct ramfuc { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 7 | struct nvkm_memx *memx; |
Ben Skeggs | b1e4553 | 2015-08-20 14:54:06 +1000 | [diff] [blame] | 8 | struct nvkm_fb *fb; |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 9 | int sequence; |
| 10 | }; |
| 11 | |
| 12 | struct ramfuc_reg { |
| 13 | int sequence; |
| 14 | bool force; |
Roy Spliet | 930da22 | 2014-09-12 18:00:15 +0200 | [diff] [blame] | 15 | u32 addr; |
| 16 | u32 stride; /* in bytes */ |
| 17 | u32 mask; |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 18 | u32 data; |
| 19 | }; |
| 20 | |
| 21 | static inline struct ramfuc_reg |
Roy Spliet | 930da22 | 2014-09-12 18:00:15 +0200 | [diff] [blame] | 22 | ramfuc_stride(u32 addr, u32 stride, u32 mask) |
| 23 | { |
| 24 | return (struct ramfuc_reg) { |
| 25 | .sequence = 0, |
| 26 | .addr = addr, |
| 27 | .stride = stride, |
| 28 | .mask = mask, |
| 29 | .data = 0xdeadbeef, |
| 30 | }; |
| 31 | } |
| 32 | |
| 33 | static inline struct ramfuc_reg |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 34 | ramfuc_reg2(u32 addr1, u32 addr2) |
| 35 | { |
| 36 | return (struct ramfuc_reg) { |
| 37 | .sequence = 0, |
Roy Spliet | 930da22 | 2014-09-12 18:00:15 +0200 | [diff] [blame] | 38 | .addr = addr1, |
| 39 | .stride = addr2 - addr1, |
| 40 | .mask = 0x3, |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 41 | .data = 0xdeadbeef, |
| 42 | }; |
| 43 | } |
| 44 | |
Stéphane Marchesin | 3c4be80 | 2014-06-27 13:17:25 -0700 | [diff] [blame] | 45 | static noinline struct ramfuc_reg |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 46 | ramfuc_reg(u32 addr) |
| 47 | { |
Roy Spliet | 930da22 | 2014-09-12 18:00:15 +0200 | [diff] [blame] | 48 | return (struct ramfuc_reg) { |
| 49 | .sequence = 0, |
| 50 | .addr = addr, |
| 51 | .stride = 0, |
| 52 | .mask = 0x1, |
| 53 | .data = 0xdeadbeef, |
| 54 | }; |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | static inline int |
Ben Skeggs | b1e4553 | 2015-08-20 14:54:06 +1000 | [diff] [blame] | 58 | ramfuc_init(struct ramfuc *ram, struct nvkm_fb *fb) |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 59 | { |
Ben Skeggs | 03c8952 | 2015-08-20 14:54:20 +1000 | [diff] [blame] | 60 | int ret = nvkm_memx_init(fb->subdev.device->pmu, &ram->memx); |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 61 | if (ret) |
| 62 | return ret; |
| 63 | |
| 64 | ram->sequence++; |
Ben Skeggs | b1e4553 | 2015-08-20 14:54:06 +1000 | [diff] [blame] | 65 | ram->fb = fb; |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 66 | return 0; |
| 67 | } |
| 68 | |
| 69 | static inline int |
| 70 | ramfuc_exec(struct ramfuc *ram, bool exec) |
| 71 | { |
| 72 | int ret = 0; |
Ben Skeggs | b1e4553 | 2015-08-20 14:54:06 +1000 | [diff] [blame] | 73 | if (ram->fb) { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 74 | ret = nvkm_memx_fini(&ram->memx, exec); |
Ben Skeggs | b1e4553 | 2015-08-20 14:54:06 +1000 | [diff] [blame] | 75 | ram->fb = NULL; |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 76 | } |
| 77 | return ret; |
| 78 | } |
| 79 | |
| 80 | static inline u32 |
| 81 | ramfuc_rd32(struct ramfuc *ram, struct ramfuc_reg *reg) |
| 82 | { |
Ben Skeggs | 6758745 | 2015-08-20 14:54:09 +1000 | [diff] [blame] | 83 | struct nvkm_device *device = ram->fb->subdev.device; |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 84 | if (reg->sequence != ram->sequence) |
Ben Skeggs | 6758745 | 2015-08-20 14:54:09 +1000 | [diff] [blame] | 85 | reg->data = nvkm_rd32(device, reg->addr); |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 86 | return reg->data; |
| 87 | } |
| 88 | |
| 89 | static inline void |
| 90 | ramfuc_wr32(struct ramfuc *ram, struct ramfuc_reg *reg, u32 data) |
| 91 | { |
Roy Spliet | 930da22 | 2014-09-12 18:00:15 +0200 | [diff] [blame] | 92 | unsigned int mask, off = 0; |
| 93 | |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 94 | reg->sequence = ram->sequence; |
| 95 | reg->data = data; |
Roy Spliet | 930da22 | 2014-09-12 18:00:15 +0200 | [diff] [blame] | 96 | |
| 97 | for (mask = reg->mask; mask > 0; mask = (mask & ~1) >> 1) { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 98 | if (mask & 1) |
| 99 | nvkm_memx_wr32(ram->memx, reg->addr+off, reg->data); |
Roy Spliet | 930da22 | 2014-09-12 18:00:15 +0200 | [diff] [blame] | 100 | off += reg->stride; |
| 101 | } |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | static inline void |
| 105 | ramfuc_nuke(struct ramfuc *ram, struct ramfuc_reg *reg) |
| 106 | { |
| 107 | reg->force = true; |
| 108 | } |
| 109 | |
| 110 | static inline u32 |
| 111 | ramfuc_mask(struct ramfuc *ram, struct ramfuc_reg *reg, u32 mask, u32 data) |
| 112 | { |
| 113 | u32 temp = ramfuc_rd32(ram, reg); |
| 114 | if (temp != ((temp & ~mask) | data) || reg->force) { |
| 115 | ramfuc_wr32(ram, reg, (temp & ~mask) | data); |
| 116 | reg->force = false; |
| 117 | } |
| 118 | return temp; |
| 119 | } |
| 120 | |
| 121 | static inline void |
| 122 | ramfuc_wait(struct ramfuc *ram, u32 addr, u32 mask, u32 data, u32 nsec) |
| 123 | { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 124 | nvkm_memx_wait(ram->memx, addr, mask, data, nsec); |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | static inline void |
| 128 | ramfuc_nsec(struct ramfuc *ram, u32 nsec) |
| 129 | { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 130 | nvkm_memx_nsec(ram->memx, nsec); |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 131 | } |
| 132 | |
Roy Spliet | e1a6f7d | 2014-09-04 16:58:49 +0200 | [diff] [blame] | 133 | static inline void |
| 134 | ramfuc_wait_vblank(struct ramfuc *ram) |
| 135 | { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 136 | nvkm_memx_wait_vblank(ram->memx); |
Roy Spliet | e1a6f7d | 2014-09-04 16:58:49 +0200 | [diff] [blame] | 137 | } |
| 138 | |
Roy Spliet | d93e996 | 2014-09-04 16:58:50 +0200 | [diff] [blame] | 139 | static inline void |
Roy Spliet | 7f4b961 | 2014-10-02 18:01:52 +0200 | [diff] [blame] | 140 | ramfuc_train(struct ramfuc *ram) |
| 141 | { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 142 | nvkm_memx_train(ram->memx); |
Roy Spliet | 7f4b961 | 2014-10-02 18:01:52 +0200 | [diff] [blame] | 143 | } |
| 144 | |
| 145 | static inline int |
Ben Skeggs | b1e4553 | 2015-08-20 14:54:06 +1000 | [diff] [blame] | 146 | ramfuc_train_result(struct nvkm_fb *fb, u32 *result, u32 rsize) |
Roy Spliet | 7f4b961 | 2014-10-02 18:01:52 +0200 | [diff] [blame] | 147 | { |
Ben Skeggs | 03c8952 | 2015-08-20 14:54:20 +1000 | [diff] [blame] | 148 | return nvkm_memx_train_result(fb->subdev.device->pmu, result, rsize); |
Roy Spliet | 7f4b961 | 2014-10-02 18:01:52 +0200 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | static inline void |
Ben Skeggs | 630a6a4 | 2014-09-11 22:59:13 +1000 | [diff] [blame] | 152 | ramfuc_block(struct ramfuc *ram) |
Roy Spliet | d93e996 | 2014-09-04 16:58:50 +0200 | [diff] [blame] | 153 | { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 154 | nvkm_memx_block(ram->memx); |
Roy Spliet | d93e996 | 2014-09-04 16:58:50 +0200 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | static inline void |
Ben Skeggs | 630a6a4 | 2014-09-11 22:59:13 +1000 | [diff] [blame] | 158 | ramfuc_unblock(struct ramfuc *ram) |
Roy Spliet | d93e996 | 2014-09-04 16:58:50 +0200 | [diff] [blame] | 159 | { |
Ben Skeggs | 639c308 | 2015-01-14 14:52:58 +1000 | [diff] [blame] | 160 | nvkm_memx_unblock(ram->memx); |
Roy Spliet | d93e996 | 2014-09-04 16:58:50 +0200 | [diff] [blame] | 161 | } |
| 162 | |
Roy Spliet | e1a6f7d | 2014-09-04 16:58:49 +0200 | [diff] [blame] | 163 | #define ram_init(s,p) ramfuc_init(&(s)->base, (p)) |
| 164 | #define ram_exec(s,e) ramfuc_exec(&(s)->base, (e)) |
Roy Spliet | 930da22 | 2014-09-12 18:00:15 +0200 | [diff] [blame] | 165 | #define ram_have(s,r) ((s)->r_##r.addr != 0x000000) |
Roy Spliet | e1a6f7d | 2014-09-04 16:58:49 +0200 | [diff] [blame] | 166 | #define ram_rd32(s,r) ramfuc_rd32(&(s)->base, &(s)->r_##r) |
| 167 | #define ram_wr32(s,r,d) ramfuc_wr32(&(s)->base, &(s)->r_##r, (d)) |
| 168 | #define ram_nuke(s,r) ramfuc_nuke(&(s)->base, &(s)->r_##r) |
| 169 | #define ram_mask(s,r,m,d) ramfuc_mask(&(s)->base, &(s)->r_##r, (m), (d)) |
| 170 | #define ram_wait(s,r,m,d,n) ramfuc_wait(&(s)->base, (r), (m), (d), (n)) |
| 171 | #define ram_nsec(s,n) ramfuc_nsec(&(s)->base, (n)) |
| 172 | #define ram_wait_vblank(s) ramfuc_wait_vblank(&(s)->base) |
Roy Spliet | 7f4b961 | 2014-10-02 18:01:52 +0200 | [diff] [blame] | 173 | #define ram_train(s) ramfuc_train(&(s)->base) |
| 174 | #define ram_train_result(s,r,l) ramfuc_train_result((s), (r), (l)) |
Ben Skeggs | 630a6a4 | 2014-09-11 22:59:13 +1000 | [diff] [blame] | 175 | #define ram_block(s) ramfuc_block(&(s)->base) |
| 176 | #define ram_unblock(s) ramfuc_unblock(&(s)->base) |
Ben Skeggs | aae95ca | 2013-03-04 15:01:37 +1000 | [diff] [blame] | 177 | #endif |