#define DRM_V3D_MMAP_BO 0x03
#define DRM_V3D_GET_PARAM 0x04
#define DRM_V3D_GET_BO_OFFSET 0x05
+#define DRM_V3D_SUBMIT_TFU 0x06
#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
#define DRM_IOCTL_V3D_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_MMAP_BO, struct drm_v3d_mmap_bo)
#define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
#define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
+#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
/**
* struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
* coordinate shader to determine where primitives land on the screen,
* then writes out the state updates and draw calls necessary per tile
* to the tile allocation BO.
+ *
+ * This BCL will block on any previous BCL submitted on the
+ * same FD, but not on any RCL or BCLs submitted by other
+ * clients -- that is left up to the submitter to control
+ * using in_sync_bcl if necessary.
*/
__u32 bcl_start;
- /** End address of the BCL (first byte after the BCL) */
+ /** End address of the BCL (first byte after the BCL) */
__u32 bcl_end;
/* Offset of the render command list.
* This is the second set of commands executed, which will either
* execute the tiles that have been set up by the BCL, or a fixed set
* of tiles (in the case of RCL-only blits).
+ *
+ * This RCL will block on this submit's BCL, and any previous
+ * RCL submitted on the same FD, but not on any RCL or BCLs
+ * submitted by other clients -- that is left up to the
+ * submitter to control using in_sync_rcl if necessary.
*/
__u32 rcl_start;
- /** End address of the RCL (first byte after the RCL) */
+ /** End address of the RCL (first byte after the RCL) */
__u32 rcl_end;
/** An optional sync object to wait on before starting the BCL. */
DRM_V3D_PARAM_V3D_CORE0_IDENT0,
DRM_V3D_PARAM_V3D_CORE0_IDENT1,
DRM_V3D_PARAM_V3D_CORE0_IDENT2,
+ DRM_V3D_PARAM_SUPPORTS_TFU,
};
struct drm_v3d_get_param {
__u32 offset;
};
+struct drm_v3d_submit_tfu {
+ __u32 icfg;
+ __u32 iia;
+ __u32 iis;
+ __u32 ica;
+ __u32 iua;
+ __u32 ioa;
+ __u32 ios;
+ __u32 coef[4];
+ /* First handle is the output BO, following are other inputs.
+ * 0 for unused.
+ */
+ __u32 bo_handles[4];
+ /* sync object to block on before running the TFU job. Each TFU
+ * job will execute in the order submitted to its FD. Synchronization
+ * against rendering jobs requires using sync objects.
+ */
+ __u32 in_sync;
+ /* Sync object to signal when the TFU job is done. */
+ __u32 out_sync;
+};
+
#if defined(__cplusplus)
}
#endif
return entry ? entry->data : NULL;
}
+static void
+v3d_simulator_copy_in_handle(struct v3d_simulator_file *file, int handle)
+{
+ struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, handle);
+
+ if (!sim_bo)
+ return;
+
+ memcpy(sim_bo->sim_vaddr, sim_bo->gem_vaddr, sim_bo->size);
+}
+
+static void
+v3d_simulator_copy_out_handle(struct v3d_simulator_file *file, int handle)
+{
+ struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, handle);
+
+ if (!sim_bo)
+ return;
+
+ memcpy(sim_bo->gem_vaddr, sim_bo->sim_vaddr, sim_bo->size);
+
+ if (*(uint32_t *)(sim_bo->sim_vaddr +
+ sim_bo->size) != BO_SENTINEL) {
+ fprintf(stderr, "Buffer overflow in handle %d\n",
+ handle);
+ }
+}
+
static int
v3d_simulator_pin_bos(struct v3d_simulator_file *file,
struct drm_v3d_submit_cl *submit)
{
uint32_t *bo_handles = (uint32_t *)(uintptr_t)submit->bo_handles;
- for (int i = 0; i < submit->bo_handle_count; i++) {
- int handle = bo_handles[i];
- struct v3d_simulator_bo *sim_bo =
- v3d_get_simulator_bo(file, handle);
-
- memcpy(sim_bo->sim_vaddr, sim_bo->gem_vaddr, sim_bo->size);
- }
+ for (int i = 0; i < submit->bo_handle_count; i++)
+ v3d_simulator_copy_in_handle(file, bo_handles[i]);
return 0;
}
{
uint32_t *bo_handles = (uint32_t *)(uintptr_t)submit->bo_handles;
- for (int i = 0; i < submit->bo_handle_count; i++) {
- int handle = bo_handles[i];
- struct v3d_simulator_bo *sim_bo =
- v3d_get_simulator_bo(file, handle);
-
- memcpy(sim_bo->gem_vaddr, sim_bo->sim_vaddr, sim_bo->size);
-
- if (*(uint32_t *)(sim_bo->sim_vaddr +
- sim_bo->size) != BO_SENTINEL) {
- fprintf(stderr, "Buffer overflow in handle %d\n",
- handle);
- }
- }
+ for (int i = 0; i < submit->bo_handle_count; i++)
+ v3d_simulator_copy_out_handle(file, bo_handles[i]);
return 0;
}
return v3d33_simulator_get_param_ioctl(sim_state.v3d, args);
}
+static int
+v3d_simulator_submit_tfu_ioctl(int fd, struct drm_v3d_submit_tfu *args)
+{
+ struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd);
+ int ret;
+
+ v3d_simulator_copy_in_handle(file, args->bo_handles[0]);
+ v3d_simulator_copy_in_handle(file, args->bo_handles[1]);
+ v3d_simulator_copy_in_handle(file, args->bo_handles[2]);
+ v3d_simulator_copy_in_handle(file, args->bo_handles[3]);
+
+ if (sim_state.ver >= 41)
+ ret = v3d41_simulator_submit_tfu_ioctl(sim_state.v3d, args);
+ else
+ ret = v3d33_simulator_submit_tfu_ioctl(sim_state.v3d, args);
+
+ v3d_simulator_copy_out_handle(file, args->bo_handles[0]);
+
+ return ret;
+}
+
int
v3d_simulator_ioctl(int fd, unsigned long request, void *args)
{
case DRM_IOCTL_GEM_CLOSE:
return v3d_simulator_gem_close_ioctl(fd, args);
+ case DRM_IOCTL_V3D_SUBMIT_TFU:
+ return v3d_simulator_submit_tfu_ioctl(fd, args);
+
case DRM_IOCTL_GEM_OPEN:
case DRM_IOCTL_GEM_FLINK:
return drmIoctl(fd, request, args);
void v3dX(simulator_submit_cl_ioctl)(struct v3d_hw *v3d,
struct drm_v3d_submit_cl *args,
uint32_t gmp_offset);
+int v3dX(simulator_submit_tfu_ioctl)(struct v3d_hw *v3d,
+ struct drm_v3d_submit_tfu *args);
const struct v3d_format *v3dX(get_format_desc)(enum pipe_format f);
void v3dX(get_internal_type_bpp_for_output_format)(uint32_t format,
uint32_t *type,
v3d_flush_slices(v3d);
}
+int
+v3dX(simulator_submit_tfu_ioctl)(struct v3d_hw *v3d,
+ struct drm_v3d_submit_tfu *args)
+{
+ int last_vtct = V3D_READ(V3D_TFU_CS) & V3D_TFU_CS_CVTCT_SET;
+
+ V3D_WRITE(V3D_TFU_IIA, args->iia);
+ V3D_WRITE(V3D_TFU_IIS, args->iis);
+ V3D_WRITE(V3D_TFU_ICA, args->ica);
+ V3D_WRITE(V3D_TFU_IUA, args->iua);
+ V3D_WRITE(V3D_TFU_IOA, args->ioa);
+ V3D_WRITE(V3D_TFU_IOS, args->ios);
+ V3D_WRITE(V3D_TFU_COEF0, args->coef[0]);
+ V3D_WRITE(V3D_TFU_COEF1, args->coef[1]);
+ V3D_WRITE(V3D_TFU_COEF2, args->coef[2]);
+ V3D_WRITE(V3D_TFU_COEF3, args->coef[3]);
+
+ V3D_WRITE(V3D_TFU_ICFG, args->icfg);
+
+ while ((V3D_READ(V3D_TFU_CS) & V3D_TFU_CS_CVTCT_SET) != last_vtct) {
+ v3d_hw_tick(v3d);
+ }
+
+ return 0;
+}
+
int
v3dX(simulator_get_param_ioctl)(struct v3d_hw *v3d,
struct drm_v3d_get_param *args)
[DRM_V3D_PARAM_V3D_CORE0_IDENT2] = V3D_CTL_0_IDENT2,
};
+ switch (args->param) {
+ case DRM_V3D_PARAM_SUPPORTS_TFU:
+ args->value = 1;
+ return 0;
+ }
+
if (args->param < ARRAY_SIZE(reg_map) && reg_map[args->param]) {
args->value = V3D_READ(reg_map[args->param]);
return 0;