1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-11-11     GuEe-GUI     the first version
9  */
10 
11 #ifndef __VIRTIO_GPU_H__
12 #define __VIRTIO_GPU_H__
13 
14 #include <rtdef.h>
15 
16 #include <virtio.h>
17 
18 #define VIRTIO_GPU_QUEUE_CTRL       0
19 #define VIRTIO_GPU_QUEUE_CURSOR     1
20 #define VIRTIO_GPU_QUEUE_SIZE       32
21 
22 #define VIRTIO_GPU_F_VIRGL          0   /* VIRTIO_GPU_CMD_CTX_*, VIRTIO_GPU_CMD_*_3D */
23 #define VIRTIO_GPU_F_EDID           1   /* VIRTIO_GPU_CMD_GET_EDID */
24 #define VIRTIO_GPU_F_RESOURCE_UUID  2   /* VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID */
25 #define VIRTIO_GPU_F_RESOURCE_BLOB  3   /* VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB */
26 #define VIRTIO_GPU_F_CONTEXT_INIT   4   /* VIRTIO_GPU_CMD_CREATE_CONTEXT with context_init and multiple timelines */
27 
28 #define VIRTIO_GPU_EVENT_DISPLAY    (1 << 0)
29 
30 #define VIRTIO_GPU_FORMAT_BPP       32
31 #define VIRTIO_GPU_FORMAT_PIXEL     4
32 #define VIRTIO_GPU_CURSOR_WIDTH     64
33 #define VIRTIO_GPU_CURSOR_HEIGHT    64
34 #define VIRTIO_GPU_CURSOR_IMG_SIZE  (VIRTIO_GPU_CURSOR_WIDTH * VIRTIO_GPU_CURSOR_HEIGHT * VIRTIO_GPU_FORMAT_PIXEL)
35 #define VIRTIO_GPU_INVALID_PMODE_ID RT_UINT32_MAX
36 
37 /* GPU control */
38 
39 struct virtio_gpu_config
40 {
41     rt_uint32_t events_read;
42     rt_uint32_t events_clear;
43     rt_uint32_t num_scanouts;   /* 1 ~ 16 */
44     rt_uint32_t reserved;
45 };
46 
47 enum virtio_gpu_ctrl_type
48 {
49     VIRTIO_GPU_UNDEFINED = 0,
50 
51     /* 2d commands */
52     VIRTIO_GPU_CMD_GET_DISPLAY_INFO = 0x0100,
53     VIRTIO_GPU_CMD_RESOURCE_CREATE_2D,
54     VIRTIO_GPU_CMD_RESOURCE_UNREF,
55     VIRTIO_GPU_CMD_SET_SCANOUT,
56     VIRTIO_GPU_CMD_RESOURCE_FLUSH,
57     VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D,
58     VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING,
59     VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING,
60     VIRTIO_GPU_CMD_GET_CAPSET_INFO,
61     VIRTIO_GPU_CMD_GET_CAPSET,
62     VIRTIO_GPU_CMD_GET_EDID,
63     VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID,
64     VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB,
65     VIRTIO_GPU_CMD_SET_SCANOUT_BLOB,
66 
67     /* 3d commands */
68     VIRTIO_GPU_CMD_CTX_CREATE = 0x0200,
69     VIRTIO_GPU_CMD_CTX_DESTROY,
70     VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE,
71     VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE,
72     VIRTIO_GPU_CMD_RESOURCE_CREATE_3D,
73     VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D,
74     VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D,
75     VIRTIO_GPU_CMD_SUBMIT_3D,
76     VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB,
77     VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB,
78 
79     /* cursor commands */
80     VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300,
81     VIRTIO_GPU_CMD_MOVE_CURSOR,
82 
83     /* success responses */
84     VIRTIO_GPU_RESP_OK_NODATA = 0x1100,
85     VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
86     VIRTIO_GPU_RESP_OK_CAPSET_INFO,
87     VIRTIO_GPU_RESP_OK_CAPSET,
88     VIRTIO_GPU_RESP_OK_EDID,
89     VIRTIO_GPU_RESP_OK_RESOURCE_UUID,
90     VIRTIO_GPU_RESP_OK_MAP_INFO,
91 
92     /* error responses */
93     VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
94     VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY,
95     VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID,
96     VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID,
97     VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID,
98     VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER,
99 };
100 
101 #define VIRTIO_GPU_FLAG_FENCE (1 << 0)
102 
103 struct virtio_gpu_ctrl_hdr
104 {
105     rt_uint32_t type;
106     rt_uint32_t flags;
107     rt_uint64_t fence_id;
108     rt_uint32_t ctx_id;
109     rt_uint8_t ring_idx;
110     rt_uint8_t padding[3];
111 };
112 
113 #define VIRTIO_GPU_MAX_SCANOUTS 16
114 
115 struct virtio_gpu_rect
116 {
117     rt_uint32_t x;
118     rt_uint32_t y;
119     rt_uint32_t width;
120     rt_uint32_t height;
121 };
122 
123 struct virtio_gpu_resp_display_info
124 {
125     struct virtio_gpu_ctrl_hdr hdr;
126     struct virtio_gpu_display_one
127     {
128         struct virtio_gpu_rect r;
129         rt_uint32_t enabled;
130         rt_uint32_t flags;
131     } pmodes[VIRTIO_GPU_MAX_SCANOUTS];
132 };
133 
134 struct virtio_gpu_get_edid
135 {
136     struct virtio_gpu_ctrl_hdr hdr;
137     rt_uint32_t scanout;
138     rt_uint32_t padding;
139 };
140 
141 struct virtio_gpu_resp_edid
142 {
143     struct virtio_gpu_ctrl_hdr hdr;
144     rt_uint32_t size;
145     rt_uint32_t padding;
146     rt_uint8_t edid[1024];
147 };
148 
149 enum virtio_gpu_formats
150 {
151     VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM = 1,
152     VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM = 2,
153     VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM = 3,
154     VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM = 4,
155 
156     VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM = 67,
157     VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM = 68,
158 
159     VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM = 121,
160     VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM = 134,
161 };
162 
163 struct virtio_gpu_resource_create_2d
164 {
165     struct virtio_gpu_ctrl_hdr hdr;
166     rt_uint32_t resource_id;
167     rt_uint32_t format;
168     rt_uint32_t width;
169     rt_uint32_t height;
170 };
171 
172 struct virtio_gpu_resource_unref
173 {
174     struct virtio_gpu_ctrl_hdr hdr;
175     rt_uint32_t resource_id;
176     rt_uint32_t padding;
177 };
178 
179 struct virtio_gpu_set_scanout
180 {
181     struct virtio_gpu_ctrl_hdr hdr;
182     struct virtio_gpu_rect r;
183     rt_uint32_t scanout_id;
184     rt_uint32_t resource_id;
185 };
186 
187 struct virtio_gpu_resource_flush
188 {
189     struct virtio_gpu_ctrl_hdr hdr;
190     struct virtio_gpu_rect r;
191     rt_uint32_t resource_id;
192     rt_uint32_t padding;
193 };
194 
195 struct virtio_gpu_transfer_to_host_2d
196 {
197     struct virtio_gpu_ctrl_hdr hdr;
198     struct virtio_gpu_rect r;
199     rt_uint64_t offset;
200     rt_uint32_t resource_id;
201     rt_uint32_t padding;
202 };
203 
204 struct virtio_gpu_resource_attach_backing
205 {
206     struct virtio_gpu_ctrl_hdr hdr;
207     rt_uint32_t resource_id;
208     rt_uint32_t nr_entries;
209 };
210 
211 struct virtio_gpu_mem_entry
212 {
213     rt_uint64_t addr;
214     rt_uint32_t length;
215     rt_uint32_t padding;
216 };
217 
218 struct virtio_gpu_resource_detach_backing
219 {
220     struct virtio_gpu_ctrl_hdr hdr;
221     rt_uint32_t resource_id;
222     rt_uint32_t padding;
223 };
224 
225 struct virtio_gpu_get_capset_info
226 {
227     struct virtio_gpu_ctrl_hdr hdr;
228     rt_uint32_t capset_index;
229     rt_uint32_t padding;
230 };
231 
232 #define VIRTIO_GPU_CAPSET_VIRGL         1
233 #define VIRTIO_GPU_CAPSET_VIRGL2        2
234 #define VIRTIO_GPU_CAPSET_GFXSTREAM     3
235 #define VIRTIO_GPU_CAPSET_VENUS         4
236 #define VIRTIO_GPU_CAPSET_CROSS_DOMAIN  5
237 
238 struct virtio_gpu_resp_capset_info
239 {
240     struct virtio_gpu_ctrl_hdr hdr;
241     rt_uint32_t capset_id;
242     rt_uint32_t capset_max_version;
243     rt_uint32_t capset_max_size;
244     rt_uint32_t padding;
245 };
246 
247 struct virtio_gpu_get_capset
248 {
249     struct virtio_gpu_ctrl_hdr hdr;
250     rt_uint32_t capset_id;
251     rt_uint32_t capset_version;
252 };
253 
254 struct virtio_gpu_resp_capset
255 {
256     struct virtio_gpu_ctrl_hdr hdr;
257     rt_uint8_t capset_data[];
258 };
259 
260 struct virtio_gpu_resource_assign_uuid
261 {
262     struct virtio_gpu_ctrl_hdr hdr;
263     rt_uint32_t resource_id;
264     rt_uint32_t padding;
265 };
266 
267 struct virtio_gpu_resp_resource_uuid
268 {
269     struct virtio_gpu_ctrl_hdr hdr;
270     rt_uint8_t uuid[16];
271 };
272 
273 #define VIRTIO_GPU_BLOB_MEM_GUEST             0x0001
274 #define VIRTIO_GPU_BLOB_MEM_HOST3D            0x0002
275 #define VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST      0x0003
276 
277 #define VIRTIO_GPU_BLOB_FLAG_USE_MAPPABLE     0x0001
278 #define VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE    0x0002
279 #define VIRTIO_GPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
280 
281 struct virtio_gpu_resource_create_blob
282 {
283     struct virtio_gpu_ctrl_hdr hdr;
284     rt_uint32_t resource_id;
285     rt_uint32_t blob_mem;
286     rt_uint32_t blob_flags;
287     rt_uint32_t nr_entries;
288     rt_uint64_t blob_id;
289     rt_uint64_t size;
290 };
291 
292 struct virtio_gpu_set_scanout_blob
293 {
294     struct virtio_gpu_ctrl_hdr hdr;
295     struct virtio_gpu_rect r;
296     rt_uint32_t scanout_id;
297     rt_uint32_t resource_id;
298     rt_uint32_t width;
299     rt_uint32_t height;
300     rt_uint32_t format;
301     rt_uint32_t padding;
302     rt_uint32_t strides[4];
303     rt_uint32_t offsets[4];
304 };
305 
306 #define VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK 0x000000ff
307 struct virtio_gpu_ctx_create
308 {
309     struct virtio_gpu_ctrl_hdr hdr;
310     rt_uint32_t nlen;
311     rt_uint32_t context_init;
312     char debug_name[64];
313 };
314 
315 struct virtio_gpu_resource_map_blob
316 {
317     struct virtio_gpu_ctrl_hdr hdr;
318     rt_uint32_t resource_id;
319     rt_uint32_t padding;
320     rt_uint64_t offset;
321 };
322 
323 #define VIRTIO_GPU_MAP_CACHE_MASK      0x0f
324 #define VIRTIO_GPU_MAP_CACHE_NONE      0x00
325 #define VIRTIO_GPU_MAP_CACHE_CACHED    0x01
326 #define VIRTIO_GPU_MAP_CACHE_UNCACHED  0x02
327 #define VIRTIO_GPU_MAP_CACHE_WC        0x03
328 
329 struct virtio_gpu_resp_map_info
330 {
331     struct virtio_gpu_ctrl_hdr hdr;
332     rt_uint32_t map_info;
333     rt_uint32_t padding;
334 };
335 
336 struct virtio_gpu_resource_unmap_blob
337 {
338     struct virtio_gpu_ctrl_hdr hdr;
339     rt_uint32_t resource_id;
340     rt_uint32_t padding;
341 };
342 
343 /* GPU cursor */
344 
345 struct virtio_gpu_cursor_pos
346 {
347     rt_uint32_t scanout_id;
348     rt_uint32_t x;
349     rt_uint32_t y;
350     rt_uint32_t padding;
351 };
352 
353 struct virtio_gpu_update_cursor
354 {
355     struct virtio_gpu_ctrl_hdr hdr;
356     struct virtio_gpu_cursor_pos pos;
357     rt_uint32_t resource_id;
358     rt_uint32_t hot_x;
359     rt_uint32_t hot_y;
360     rt_uint32_t padding;
361 };
362 
363 struct virtio_gpu_device
364 {
365     struct rt_device parent;
366 
367     struct virtio_device virtio_dev;
368 
369     /* Current display's info */
370     struct virtio_gpu_display_one pmode;
371     enum virtio_gpu_formats format;
372     rt_uint32_t pmode_id;
373     rt_uint32_t cursor_x, cursor_y;
374     rt_uint32_t display_resource_id;
375     rt_uint32_t cursor_resource_id;
376     rt_uint32_t next_resource_id;
377 
378     /* Display framebuffer */
379     struct rt_mutex rw_mutex;
380     void *framebuffer;
381     rt_uint32_t smem_len;
382 
383     /* Cursor image info */
384     rt_bool_t cursor_enable;
385     struct rt_mutex ops_mutex;
386     rt_uint8_t cursor_img[VIRTIO_GPU_CURSOR_IMG_SIZE];
387 
388     /* GPU request info */
389     struct virtio_gpu_resp_display_info gpu_request;
390 
391     struct
392     {
393         rt_bool_t ctrl_valid;
394         rt_bool_t cursor_valid;
395 
396         struct virtio_gpu_update_cursor cursor_cmd;
397     } info[VIRTIO_GPU_QUEUE_SIZE];
398 };
399 
400 rt_err_t rt_virtio_gpu_init(rt_ubase_t *mmio_base, rt_uint32_t irq);
401 
402 enum
403 {
404     VIRTIO_DEVICE_CTRL_GPU_SET_PRIMARY      = 0x20,
405     VIRTIO_DEVICE_CTRL_GPU_CREATE_2D,
406 
407     VIRTIO_DEVICE_CTRL_CURSOR_SETUP,
408     VIRTIO_DEVICE_CTRL_CURSOR_SET_IMG,
409     VIRTIO_DEVICE_CTRL_CURSOR_MOVE,
410 };
411 
412 #endif /* __VIRTIO_GPU_H__ */
413