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