#ifndef __NVKM_BUS_HWSQ_H__ #define __NVKM_BUS_HWSQ_H__ #include struct hwsq { struct nvkm_subdev *subdev; struct nvkm_hwsq *hwsq; int sequence; }; struct hwsq_reg { int sequence; bool force; u32 addr; u32 stride; /* in bytes */ u32 mask; u32 data; }; static inline struct hwsq_reg hwsq_stride(u32 addr, u32 stride, u32 mask) { return (struct hwsq_reg) { .sequence = 0, .force = 0, .addr = addr, .stride = stride, .mask = mask, .data = 0xdeadbeef, }; } static inline struct hwsq_reg hwsq_reg2(u32 addr1, u32 addr2) { return (struct hwsq_reg) { .sequence = 0, .force = 0, .addr = addr1, .stride = addr2 - addr1, .mask = 0x3, .data = 0xdeadbeef, }; } static inline struct hwsq_reg hwsq_reg(u32 addr) { return (struct hwsq_reg) { .sequence = 0, .force = 0, .addr = addr, .stride = 0, .mask = 0x1, .data = 0xdeadbeef, }; } static inline int hwsq_init(struct hwsq *ram, struct nvkm_subdev *subdev) { int ret; ret = nvkm_hwsq_init(subdev, &ram->hwsq); if (ret) return ret; ram->sequence++; ram->subdev = subdev; return 0; } static inline int hwsq_exec(struct hwsq *ram, bool exec) { int ret = 0; if (ram->subdev) { ret = nvkm_hwsq_fini(&ram->hwsq, exec); ram->subdev = NULL; } return ret; } static inline u32 hwsq_rd32(struct hwsq *ram, struct hwsq_reg *reg) { struct nvkm_device *device = ram->subdev->device; if (reg->sequence != ram->sequence) reg->data = nvkm_rd32(device, reg->addr); return reg->data; } static inline void hwsq_wr32(struct hwsq *ram, struct hwsq_reg *reg, u32 data) { u32 mask, off = 0; reg->sequence = ram->sequence; reg->data = data; for (mask = reg->mask; mask > 0; mask = (mask & ~1) >> 1) { if (mask & 1) nvkm_hwsq_wr32(ram->hwsq, reg->addr+off, reg->data); off += reg->stride; } } static inline void hwsq_nuke(struct hwsq *ram, struct hwsq_reg *reg) { reg->force = true; } static inline u32 hwsq_mask(struct hwsq *ram, struct hwsq_reg *reg, u32 mask, u32 data) { u32 temp = hwsq_rd32(ram, reg); if (temp != ((temp & ~mask) | data) || reg->force) hwsq_wr32(ram, reg, (temp & ~mask) | data); return temp; } static inline void hwsq_setf(struct hwsq *ram, u8 flag, int data) { nvkm_hwsq_setf(ram->hwsq, flag, data); } static inline void hwsq_wait(struct hwsq *ram, u8 flag, u8 data) { nvkm_hwsq_wait(ram->hwsq, flag, data); } static inline void hwsq_wait_vblank(struct hwsq *ram) { nvkm_hwsq_wait_vblank(ram->hwsq); } static inline void hwsq_nsec(struct hwsq *ram, u32 nsec) { nvkm_hwsq_nsec(ram->hwsq, nsec); } #endif