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