1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights
7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
9bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <assert.h>
25bf215546Sopenharmony_ci#include <stdbool.h>
26bf215546Sopenharmony_ci#include <stdint.h>
27bf215546Sopenharmony_ci#include <vulkan/vulkan.h>
28bf215546Sopenharmony_ci#include <xf86drm.h>
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "pvr_private.h"
31bf215546Sopenharmony_ci#include "pvr_types.h"
32bf215546Sopenharmony_ci#include "pvr_winsys.h"
33bf215546Sopenharmony_ci#include "pvr_winsys_helper.h"
34bf215546Sopenharmony_ci#include "util/u_atomic.h"
35bf215546Sopenharmony_ci#include "vk_log.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ciint pvr_winsys_helper_display_buffer_create(int master_fd,
38bf215546Sopenharmony_ci                                            uint64_t size,
39bf215546Sopenharmony_ci                                            uint32_t *const handle_out)
40bf215546Sopenharmony_ci{
41bf215546Sopenharmony_ci   struct drm_mode_create_dumb args = {
42bf215546Sopenharmony_ci      .width = size,
43bf215546Sopenharmony_ci      .height = 1,
44bf215546Sopenharmony_ci      .bpp = 8,
45bf215546Sopenharmony_ci   };
46bf215546Sopenharmony_ci   int ret;
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   ret = drmIoctl(master_fd, DRM_IOCTL_MODE_CREATE_DUMB, &args);
49bf215546Sopenharmony_ci   if (ret)
50bf215546Sopenharmony_ci      return ret;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   *handle_out = args.handle;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   return 0;
55bf215546Sopenharmony_ci}
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ciint pvr_winsys_helper_display_buffer_destroy(int master_fd, uint32_t handle)
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci   struct drm_mode_destroy_dumb args = {
60bf215546Sopenharmony_ci      .handle = handle,
61bf215546Sopenharmony_ci   };
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   return drmIoctl(master_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &args);
64bf215546Sopenharmony_ci}
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci/* reserved_size can be 0 when no reserved area is needed. reserved_address must
67bf215546Sopenharmony_ci * be 0 if reserved_size is 0.
68bf215546Sopenharmony_ci */
69bf215546Sopenharmony_ciVkResult pvr_winsys_helper_winsys_heap_init(
70bf215546Sopenharmony_ci   struct pvr_winsys *const ws,
71bf215546Sopenharmony_ci   pvr_dev_addr_t base_address,
72bf215546Sopenharmony_ci   uint64_t size,
73bf215546Sopenharmony_ci   pvr_dev_addr_t reserved_address,
74bf215546Sopenharmony_ci   uint64_t reserved_size,
75bf215546Sopenharmony_ci   uint32_t log2_page_size,
76bf215546Sopenharmony_ci   const struct pvr_winsys_static_data_offsets *const static_data_offsets,
77bf215546Sopenharmony_ci   struct pvr_winsys_heap *const heap)
78bf215546Sopenharmony_ci{
79bf215546Sopenharmony_ci   const bool reserved_area_bottom_of_heap = reserved_address.addr ==
80bf215546Sopenharmony_ci                                             base_address.addr;
81bf215546Sopenharmony_ci   const pvr_dev_addr_t vma_heap_begin_addr =
82bf215546Sopenharmony_ci      reserved_area_bottom_of_heap
83bf215546Sopenharmony_ci         ? PVR_DEV_ADDR_OFFSET(base_address, reserved_size)
84bf215546Sopenharmony_ci         : base_address;
85bf215546Sopenharmony_ci   const uint64_t vma_heap_size = size - reserved_size;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   assert(base_address.addr);
88bf215546Sopenharmony_ci   assert(reserved_size <= size);
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci   /* As per the reserved_base powervr-km uapi documentation the reserved
91bf215546Sopenharmony_ci    * region can only be at the beginning of the heap or at the end.
92bf215546Sopenharmony_ci    * reserved_address is 0 if there is no reserved region.
93bf215546Sopenharmony_ci    * pvrsrv-km doesn't explicitly provide this info and it's assumed that it's
94bf215546Sopenharmony_ci    * always at the beginning.
95bf215546Sopenharmony_ci    */
96bf215546Sopenharmony_ci   assert(reserved_area_bottom_of_heap ||
97bf215546Sopenharmony_ci          reserved_address.addr + reserved_size == base_address.addr + size ||
98bf215546Sopenharmony_ci          (!reserved_address.addr && !reserved_size));
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   heap->ws = ws;
101bf215546Sopenharmony_ci   heap->base_addr = base_address;
102bf215546Sopenharmony_ci   heap->reserved_addr = reserved_address;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   heap->size = size;
105bf215546Sopenharmony_ci   heap->reserved_size = reserved_size;
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   heap->page_size = 1 << log2_page_size;
108bf215546Sopenharmony_ci   heap->log2_page_size = log2_page_size;
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   util_vma_heap_init(&heap->vma_heap, vma_heap_begin_addr.addr, vma_heap_size);
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   heap->vma_heap.alloc_high = false;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   /* It's expected that the heap destroy function to be the last thing that's
115bf215546Sopenharmony_ci    * called, so we start the ref_count at 0.
116bf215546Sopenharmony_ci    */
117bf215546Sopenharmony_ci   p_atomic_set(&heap->ref_count, 0);
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   if (pthread_mutex_init(&heap->lock, NULL))
120bf215546Sopenharmony_ci      return vk_error(NULL, VK_ERROR_INITIALIZATION_FAILED);
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   heap->static_data_offsets = *static_data_offsets;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   return VK_SUCCESS;
125bf215546Sopenharmony_ci}
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_cibool pvr_winsys_helper_winsys_heap_finish(struct pvr_winsys_heap *const heap)
128bf215546Sopenharmony_ci{
129bf215546Sopenharmony_ci   if (p_atomic_read(&heap->ref_count) != 0)
130bf215546Sopenharmony_ci      return false;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   pthread_mutex_destroy(&heap->lock);
133bf215546Sopenharmony_ci   util_vma_heap_finish(&heap->vma_heap);
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   return true;
136bf215546Sopenharmony_ci}
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_cibool pvr_winsys_helper_heap_alloc(struct pvr_winsys_heap *const heap,
139bf215546Sopenharmony_ci                                  uint64_t size,
140bf215546Sopenharmony_ci                                  uint64_t alignment,
141bf215546Sopenharmony_ci                                  struct pvr_winsys_vma *const vma_out)
142bf215546Sopenharmony_ci{
143bf215546Sopenharmony_ci   struct pvr_winsys_vma vma = {
144bf215546Sopenharmony_ci      .heap = heap,
145bf215546Sopenharmony_ci   };
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci   assert(util_is_power_of_two_nonzero(alignment));
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   /* pvr_srv_winsys_buffer_create() page aligns the size. We must do the same
150bf215546Sopenharmony_ci    * here to ensure enough heap space is allocated to be able to map the
151bf215546Sopenharmony_ci    * buffer to the GPU.
152bf215546Sopenharmony_ci    * We have to do this for the powervr kernel mode driver as well, as it
153bf215546Sopenharmony_ci    * returns a page aligned size when allocating buffers.
154bf215546Sopenharmony_ci    */
155bf215546Sopenharmony_ci   alignment = MAX2(alignment, heap->page_size);
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   size = ALIGN_POT(size, alignment);
158bf215546Sopenharmony_ci   vma.size = size;
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   pthread_mutex_lock(&heap->lock);
161bf215546Sopenharmony_ci   vma.dev_addr =
162bf215546Sopenharmony_ci      PVR_DEV_ADDR(util_vma_heap_alloc(&heap->vma_heap, size, heap->page_size));
163bf215546Sopenharmony_ci   pthread_mutex_unlock(&heap->lock);
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   if (!vma.dev_addr.addr) {
166bf215546Sopenharmony_ci      vk_error(NULL, VK_ERROR_OUT_OF_DEVICE_MEMORY);
167bf215546Sopenharmony_ci      return false;
168bf215546Sopenharmony_ci   }
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   p_atomic_inc(&heap->ref_count);
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   *vma_out = vma;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   return true;
175bf215546Sopenharmony_ci}
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_civoid pvr_winsys_helper_heap_free(struct pvr_winsys_vma *const vma)
178bf215546Sopenharmony_ci{
179bf215546Sopenharmony_ci   struct pvr_winsys_heap *const heap = vma->heap;
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci   /* A vma with an existing device mapping should not be freed. */
182bf215546Sopenharmony_ci   assert(!vma->bo);
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   pthread_mutex_lock(&heap->lock);
185bf215546Sopenharmony_ci   util_vma_heap_free(&heap->vma_heap, vma->dev_addr.addr, vma->size);
186bf215546Sopenharmony_ci   pthread_mutex_unlock(&heap->lock);
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   p_atomic_dec(&heap->ref_count);
189bf215546Sopenharmony_ci}
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci/* Note: the function assumes the heap allocation in the reserved memory area
192bf215546Sopenharmony_ci * can be freed with the regular heap allocation free function. The free
193bf215546Sopenharmony_ci * function gets called on mapping failure.
194bf215546Sopenharmony_ci */
195bf215546Sopenharmony_cistatic VkResult
196bf215546Sopenharmony_cipvr_buffer_create_and_map(struct pvr_winsys *const ws,
197bf215546Sopenharmony_ci                          heap_alloc_reserved_func heap_alloc_reserved,
198bf215546Sopenharmony_ci                          struct pvr_winsys_heap *heap,
199bf215546Sopenharmony_ci                          pvr_dev_addr_t dev_addr,
200bf215546Sopenharmony_ci                          uint64_t size,
201bf215546Sopenharmony_ci                          uint64_t alignment,
202bf215546Sopenharmony_ci                          struct pvr_winsys_vma **const vma_out)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   struct pvr_winsys_vma *vma;
205bf215546Sopenharmony_ci   struct pvr_winsys_bo *bo;
206bf215546Sopenharmony_ci   pvr_dev_addr_t addr;
207bf215546Sopenharmony_ci   VkResult result;
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   /* Address should not be NULL, this function is used to allocate and map
210bf215546Sopenharmony_ci    * reserved addresses and is only supposed to be used internally.
211bf215546Sopenharmony_ci    */
212bf215546Sopenharmony_ci   assert(dev_addr.addr);
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci   result = ws->ops->buffer_create(ws,
215bf215546Sopenharmony_ci                                   size,
216bf215546Sopenharmony_ci                                   alignment,
217bf215546Sopenharmony_ci                                   PVR_WINSYS_BO_TYPE_GPU,
218bf215546Sopenharmony_ci                                   PVR_WINSYS_BO_FLAG_CPU_ACCESS,
219bf215546Sopenharmony_ci                                   &bo);
220bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
221bf215546Sopenharmony_ci      return result;
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   vma = heap_alloc_reserved(heap, dev_addr, size, alignment);
224bf215546Sopenharmony_ci   if (!vma) {
225bf215546Sopenharmony_ci      result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
226bf215546Sopenharmony_ci      goto err_pvr_winsys_buffer_destroy;
227bf215546Sopenharmony_ci   }
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   addr = ws->ops->vma_map(vma, bo, 0, size);
230bf215546Sopenharmony_ci   if (!addr.addr) {
231bf215546Sopenharmony_ci      result = VK_ERROR_MEMORY_MAP_FAILED;
232bf215546Sopenharmony_ci      goto err_pvr_winsys_heap_free;
233bf215546Sopenharmony_ci   }
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   /* Note this won't destroy bo as its being used by VMA, once vma is
236bf215546Sopenharmony_ci    * unmapped, bo will be destroyed automatically.
237bf215546Sopenharmony_ci    */
238bf215546Sopenharmony_ci   ws->ops->buffer_destroy(bo);
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci   *vma_out = vma;
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci   return VK_SUCCESS;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_cierr_pvr_winsys_heap_free:
245bf215546Sopenharmony_ci   ws->ops->heap_free(vma);
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_cierr_pvr_winsys_buffer_destroy:
248bf215546Sopenharmony_ci   ws->ops->buffer_destroy(bo);
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   return result;
251bf215546Sopenharmony_ci}
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_cistatic void inline pvr_buffer_destroy_and_unmap(struct pvr_winsys_vma *vma)
254bf215546Sopenharmony_ci{
255bf215546Sopenharmony_ci   const struct pvr_winsys *const ws = vma->heap->ws;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   /* Buffer object associated with the vma will be automatically destroyed
258bf215546Sopenharmony_ci    * once vma is unmapped.
259bf215546Sopenharmony_ci    */
260bf215546Sopenharmony_ci   ws->ops->vma_unmap(vma);
261bf215546Sopenharmony_ci   ws->ops->heap_free(vma);
262bf215546Sopenharmony_ci}
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ciVkResult pvr_winsys_helper_allocate_static_memory(
265bf215546Sopenharmony_ci   struct pvr_winsys *const ws,
266bf215546Sopenharmony_ci   heap_alloc_reserved_func heap_alloc_reserved,
267bf215546Sopenharmony_ci   struct pvr_winsys_heap *const general_heap,
268bf215546Sopenharmony_ci   struct pvr_winsys_heap *const pds_heap,
269bf215546Sopenharmony_ci   struct pvr_winsys_heap *const usc_heap,
270bf215546Sopenharmony_ci   struct pvr_winsys_vma **const general_vma_out,
271bf215546Sopenharmony_ci   struct pvr_winsys_vma **const pds_vma_out,
272bf215546Sopenharmony_ci   struct pvr_winsys_vma **const usc_vma_out)
273bf215546Sopenharmony_ci{
274bf215546Sopenharmony_ci   struct pvr_winsys_vma *general_vma;
275bf215546Sopenharmony_ci   struct pvr_winsys_vma *pds_vma;
276bf215546Sopenharmony_ci   struct pvr_winsys_vma *usc_vma;
277bf215546Sopenharmony_ci   VkResult result;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   result = pvr_buffer_create_and_map(ws,
280bf215546Sopenharmony_ci                                      heap_alloc_reserved,
281bf215546Sopenharmony_ci                                      general_heap,
282bf215546Sopenharmony_ci                                      general_heap->reserved_addr,
283bf215546Sopenharmony_ci                                      general_heap->reserved_size,
284bf215546Sopenharmony_ci                                      general_heap->page_size,
285bf215546Sopenharmony_ci                                      &general_vma);
286bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
287bf215546Sopenharmony_ci      return result;
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   result = pvr_buffer_create_and_map(ws,
290bf215546Sopenharmony_ci                                      heap_alloc_reserved,
291bf215546Sopenharmony_ci                                      pds_heap,
292bf215546Sopenharmony_ci                                      pds_heap->reserved_addr,
293bf215546Sopenharmony_ci                                      pds_heap->reserved_size,
294bf215546Sopenharmony_ci                                      pds_heap->page_size,
295bf215546Sopenharmony_ci                                      &pds_vma);
296bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
297bf215546Sopenharmony_ci      goto err_pvr_buffer_destroy_and_unmap_general;
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci   result = pvr_buffer_create_and_map(ws,
300bf215546Sopenharmony_ci                                      heap_alloc_reserved,
301bf215546Sopenharmony_ci                                      usc_heap,
302bf215546Sopenharmony_ci                                      usc_heap->reserved_addr,
303bf215546Sopenharmony_ci                                      pds_heap->reserved_size,
304bf215546Sopenharmony_ci                                      usc_heap->page_size,
305bf215546Sopenharmony_ci                                      &usc_vma);
306bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
307bf215546Sopenharmony_ci      goto err_pvr_buffer_destroy_and_unmap_pds;
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci   *general_vma_out = general_vma;
310bf215546Sopenharmony_ci   *pds_vma_out = pds_vma;
311bf215546Sopenharmony_ci   *usc_vma_out = usc_vma;
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   return VK_SUCCESS;
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_cierr_pvr_buffer_destroy_and_unmap_pds:
316bf215546Sopenharmony_ci   pvr_buffer_destroy_and_unmap(pds_vma);
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_cierr_pvr_buffer_destroy_and_unmap_general:
319bf215546Sopenharmony_ci   pvr_buffer_destroy_and_unmap(general_vma);
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   return result;
322bf215546Sopenharmony_ci}
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_civoid pvr_winsys_helper_free_static_memory(
325bf215546Sopenharmony_ci   struct pvr_winsys_vma *const general_vma,
326bf215546Sopenharmony_ci   struct pvr_winsys_vma *const pds_vma,
327bf215546Sopenharmony_ci   struct pvr_winsys_vma *const usc_vma)
328bf215546Sopenharmony_ci{
329bf215546Sopenharmony_ci   pvr_buffer_destroy_and_unmap(usc_vma);
330bf215546Sopenharmony_ci   pvr_buffer_destroy_and_unmap(pds_vma);
331bf215546Sopenharmony_ci   pvr_buffer_destroy_and_unmap(general_vma);
332bf215546Sopenharmony_ci}
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_cistatic void pvr_setup_static_vdm_sync(uint8_t *const pds_ptr,
335bf215546Sopenharmony_ci                                      uint64_t pds_sync_offset_in_bytes,
336bf215546Sopenharmony_ci                                      uint8_t *const usc_ptr,
337bf215546Sopenharmony_ci                                      uint64_t usc_sync_offset_in_bytes)
338bf215546Sopenharmony_ci{
339bf215546Sopenharmony_ci   /* TODO: this needs to be auto-generated */
340bf215546Sopenharmony_ci   const uint8_t state_update[] = { 0x44, 0xA0, 0x80, 0x05,
341bf215546Sopenharmony_ci                                    0x00, 0x00, 0x00, 0xFF };
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   struct pvr_pds_kickusc_program ppp_state_update_program = { 0 };
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   memcpy(usc_ptr + usc_sync_offset_in_bytes,
346bf215546Sopenharmony_ci          state_update,
347bf215546Sopenharmony_ci          sizeof(state_update));
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci   pvr_pds_setup_doutu(&ppp_state_update_program.usc_task_control,
350bf215546Sopenharmony_ci                       usc_sync_offset_in_bytes,
351bf215546Sopenharmony_ci                       0,
352bf215546Sopenharmony_ci                       PVRX(PDSINST_DOUTU_SAMPLE_RATE_INSTANCE),
353bf215546Sopenharmony_ci                       false);
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   pvr_pds_kick_usc(&ppp_state_update_program,
356bf215546Sopenharmony_ci                    (uint32_t *)&pds_ptr[pds_sync_offset_in_bytes],
357bf215546Sopenharmony_ci                    0,
358bf215546Sopenharmony_ci                    false,
359bf215546Sopenharmony_ci                    PDS_GENERATE_CODEDATA_SEGMENTS);
360bf215546Sopenharmony_ci}
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_cistatic void
363bf215546Sopenharmony_cipvr_setup_static_pixel_event_program(uint8_t *const pds_ptr,
364bf215546Sopenharmony_ci                                     uint64_t pds_eot_offset_in_bytes)
365bf215546Sopenharmony_ci{
366bf215546Sopenharmony_ci   struct pvr_pds_event_program pixel_event_program = { 0 };
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   pvr_pds_generate_pixel_event(&pixel_event_program,
369bf215546Sopenharmony_ci                                (uint32_t *)&pds_ptr[pds_eot_offset_in_bytes],
370bf215546Sopenharmony_ci                                PDS_GENERATE_CODE_SEGMENT,
371bf215546Sopenharmony_ci                                NULL);
372bf215546Sopenharmony_ci}
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ciVkResult
375bf215546Sopenharmony_cipvr_winsys_helper_fill_static_memory(struct pvr_winsys *const ws,
376bf215546Sopenharmony_ci                                     struct pvr_winsys_vma *const general_vma,
377bf215546Sopenharmony_ci                                     struct pvr_winsys_vma *const pds_vma,
378bf215546Sopenharmony_ci                                     struct pvr_winsys_vma *const usc_vma)
379bf215546Sopenharmony_ci{
380bf215546Sopenharmony_ci   uint8_t *general_ptr, *pds_ptr, *usc_ptr;
381bf215546Sopenharmony_ci   VkResult result;
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci   general_ptr = ws->ops->buffer_map(general_vma->bo);
384bf215546Sopenharmony_ci   if (!general_ptr)
385bf215546Sopenharmony_ci      return VK_ERROR_MEMORY_MAP_FAILED;
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   pds_ptr = ws->ops->buffer_map(pds_vma->bo);
388bf215546Sopenharmony_ci   if (!pds_ptr) {
389bf215546Sopenharmony_ci      result = VK_ERROR_MEMORY_MAP_FAILED;
390bf215546Sopenharmony_ci      goto err_pvr_srv_winsys_buffer_unmap_general;
391bf215546Sopenharmony_ci   }
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_ci   usc_ptr = ws->ops->buffer_map(usc_vma->bo);
394bf215546Sopenharmony_ci   if (!usc_ptr) {
395bf215546Sopenharmony_ci      result = VK_ERROR_MEMORY_MAP_FAILED;
396bf215546Sopenharmony_ci      goto err_pvr_srv_winsys_buffer_unmap_pds;
397bf215546Sopenharmony_ci   }
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   pvr_setup_static_vdm_sync(pds_ptr,
400bf215546Sopenharmony_ci                             pds_vma->heap->static_data_offsets.vdm_sync,
401bf215546Sopenharmony_ci                             usc_ptr,
402bf215546Sopenharmony_ci                             usc_vma->heap->static_data_offsets.vdm_sync);
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci   pvr_setup_static_pixel_event_program(pds_ptr,
405bf215546Sopenharmony_ci                                        pds_vma->heap->static_data_offsets.eot);
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   /* TODO: Complete control block copying work. */
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   ws->ops->buffer_unmap(usc_vma->bo);
410bf215546Sopenharmony_ci   ws->ops->buffer_unmap(pds_vma->bo);
411bf215546Sopenharmony_ci   ws->ops->buffer_unmap(general_vma->bo);
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci   return VK_SUCCESS;
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_cierr_pvr_srv_winsys_buffer_unmap_pds:
416bf215546Sopenharmony_ci   ws->ops->buffer_unmap(pds_vma->bo);
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_cierr_pvr_srv_winsys_buffer_unmap_general:
419bf215546Sopenharmony_ci   ws->ops->buffer_unmap(general_vma->bo);
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci   return result;
422bf215546Sopenharmony_ci}
423