1 #include <lunaix/compiler.h>
2 #include <lunaix/mm/valloc.h>
3 #include <lunaix/spike.h>
4 #include <lunaix/status.h>
8 #include <klibc/string.h>
10 DEFINE_LLIST(gfxa_flat);
11 DECLARE_HASHTABLE(gfxa_idset, 8);
13 struct device_cat* gfxa_devcat = NULL;
16 static struct devclass gfxa_class = DEVCLASS(GENERIC, DISP, GFXA);
19 __gfxa_cmd_router(struct device* dev, u32_t req, va_list args)
21 struct gfxa* gfxa = (struct gfxa*)dev->underlay;
22 struct disp_profile* disp = &gfxa->disp_info;
25 case GFX_ADAPTER_INFO: {
26 struct gfxa_info* info = va_arg(args, struct gfxa_info*);
28 (struct gfxa_info){ .disp_mode = { .w_px = disp->mon.w_px,
29 .h_px = disp->mon.h_px,
30 .freq = disp->mon.freq,
31 .depth = disp->mon.depth } };
32 gfxa->ops.hwioctl(gfxa, req, args);
35 case GFX_ADAPTER_CHMODE: {
36 struct gfxa_mon* mon_info = va_arg(args, struct gfxa_mon*);
37 gfxa->disp_info.mon = *mon_info;
39 return gfxa->ops.update_profile(gfxa);
41 case GFX_ADAPTER_VMCPY:
42 case GFX_ADAPTER_LFBCPY: {
43 void* buf = va_arg(args, void*);
44 off_t off = va_arg(args, off_t);
45 size_t len = va_arg(args, size_t);
46 if (req == GFX_ADAPTER_VMCPY) {
47 return gfxa->ops.vmcpy(gfxa, buf, off, len);
49 return gfxa->ops.lfbcpy(gfxa, buf, off, len);
51 case GFX_ADAPTER_REG_WR:
52 case GFX_ADAPTER_REG_RD: {
53 u32_t* reg_addrmap = va_arg(args, u32_t*);
54 void* reg_val = va_arg(args, void*);
55 size_t reg_count = va_arg(args, size_t);
57 if (req == GFX_ADAPTER_LUT_RD) {
58 return gfxa->ops.rreads(gfxa, reg_addrmap, reg_val, reg_count);
60 return gfxa->ops.rwrites(gfxa, reg_addrmap, reg_val, reg_count);
62 case GFX_ADAPTER_LUT_RD: {
63 struct gfxa_clut* clut = va_arg(args, struct gfxa_clut*);
64 if (!clut->val || !clut->len) {
65 return disp->clut.len;
68 size_t clut_len = MIN(clut->len, disp->clut.len);
69 memcpy(clut->val, disp->clut.val, clut_len * sizeof(color_t));
72 case GFX_ADAPTER_LUT_WR: {
73 struct gfxa_clut* clut = va_arg(args, struct gfxa_clut*);
74 int err = gfxm_set_lut(gfxa, clut->val, clut->len);
76 err = gfxa->ops.update_profile(gfxa);
81 return gfxa->ops.hwioctl(gfxa, req, args);
88 gfxm_alloc_adapter(void* hw_obj)
90 if (unlikely(!gfxa_devcat)) {
91 gfxa_devcat = device_addcat(NULL, "gfx");
94 struct gfxa* gfxa = valloc(sizeof(struct gfxa));
95 struct device* gfxa_dev = device_allocsys(dev_meta(gfxa_devcat), gfxa);
97 *gfxa = (struct gfxa){ .dev = gfxa_dev, .hw_obj = hw_obj };
99 gfxa_dev->ops.exec_cmd = __gfxa_cmd_router;
105 gfxm_register(struct gfxa* gfxa)
107 gfxa->id = gfxa_class.variant++;
109 llist_append(&gfxa_flat, &gfxa->gfxas);
110 hashtable_hash_in(gfxa_idset, &gfxa->gfxas_id, gfxa->id);
112 register_device(gfxa->dev, &gfxa_class, "gfxa%d", gfxa->id);
116 gfxm_adapter(int gfxa_id)
118 struct gfxa *pos, *n;
119 hashtable_hash_foreach(gfxa_idset, gfxa_id, pos, n, gfxas_id)
121 if (pos->id == gfxa_id) {
130 gfxm_set_lut(struct gfxa* gfxa, u32_t* lut, size_t len)
132 // It is generally not feasible for graphic adapter with >256 colors still
134 if (unlikely(len > 256)) {
138 struct disp_profile* disp = &gfxa->disp_info;
139 size_t lutsz = len * sizeof(*lut);
141 if (disp->clut.len != len) {
142 vfree_safe(disp->clut.val);
143 disp->clut.val = valloc(lutsz);
144 disp->clut.len = len;
147 memcpy(disp->clut.val, lut, lutsz);