17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2018 Broadcom 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 217ec681f3Smrg * DEALINGS IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include <limits.h> 257ec681f3Smrg#include <stdio.h> 267ec681f3Smrg#include <stdlib.h> 277ec681f3Smrg#include <sys/ioctl.h> 287ec681f3Smrg#include "drm-uapi/v3d_drm.h" 297ec681f3Smrg#include "drm-shim/drm_shim.h" 307ec681f3Smrg 317ec681f3Smrgbool drm_shim_driver_prefers_first_render_node = true; 327ec681f3Smrg 337ec681f3Smrgstruct v3d_bo { 347ec681f3Smrg struct shim_bo base; 357ec681f3Smrg uint32_t offset; 367ec681f3Smrg}; 377ec681f3Smrg 387ec681f3Smrgstatic struct v3d_bo * 397ec681f3Smrgv3d_bo(struct shim_bo *bo) 407ec681f3Smrg{ 417ec681f3Smrg return (struct v3d_bo *)bo; 427ec681f3Smrg} 437ec681f3Smrg 447ec681f3Smrgstruct v3d_device { 457ec681f3Smrg uint32_t next_offset; 467ec681f3Smrg}; 477ec681f3Smrg 487ec681f3Smrgstatic struct v3d_device v3d = { 497ec681f3Smrg .next_offset = 0x1000, 507ec681f3Smrg}; 517ec681f3Smrg 527ec681f3Smrgstatic int 537ec681f3Smrgv3d_ioctl_noop(int fd, unsigned long request, void *arg) 547ec681f3Smrg{ 557ec681f3Smrg return 0; 567ec681f3Smrg} 577ec681f3Smrg 587ec681f3Smrgstatic int 597ec681f3Smrgv3d_ioctl_create_bo(int fd, unsigned long request, void *arg) 607ec681f3Smrg{ 617ec681f3Smrg struct shim_fd *shim_fd = drm_shim_fd_lookup(fd); 627ec681f3Smrg struct drm_v3d_create_bo *create = arg; 637ec681f3Smrg struct v3d_bo *bo = calloc(1, sizeof(*bo)); 647ec681f3Smrg 657ec681f3Smrg drm_shim_bo_init(&bo->base, create->size); 667ec681f3Smrg 677ec681f3Smrg assert(UINT_MAX - v3d.next_offset > create->size); 687ec681f3Smrg bo->offset = v3d.next_offset; 697ec681f3Smrg v3d.next_offset += create->size; 707ec681f3Smrg 717ec681f3Smrg create->offset = bo->offset; 727ec681f3Smrg create->handle = drm_shim_bo_get_handle(shim_fd, &bo->base); 737ec681f3Smrg 747ec681f3Smrg drm_shim_bo_put(&bo->base); 757ec681f3Smrg 767ec681f3Smrg return 0; 777ec681f3Smrg} 787ec681f3Smrg 797ec681f3Smrgstatic int 807ec681f3Smrgv3d_ioctl_get_bo_offset(int fd, unsigned long request, void *arg) 817ec681f3Smrg{ 827ec681f3Smrg struct shim_fd *shim_fd = drm_shim_fd_lookup(fd); 837ec681f3Smrg struct drm_v3d_get_bo_offset *args = arg; 847ec681f3Smrg struct shim_bo *bo = drm_shim_bo_lookup(shim_fd, args->handle); 857ec681f3Smrg 867ec681f3Smrg args->offset = v3d_bo(bo)->offset; 877ec681f3Smrg 887ec681f3Smrg drm_shim_bo_put(bo); 897ec681f3Smrg 907ec681f3Smrg return 0; 917ec681f3Smrg} 927ec681f3Smrg 937ec681f3Smrgstatic int 947ec681f3Smrgv3d_ioctl_mmap_bo(int fd, unsigned long request, void *arg) 957ec681f3Smrg{ 967ec681f3Smrg struct shim_fd *shim_fd = drm_shim_fd_lookup(fd); 977ec681f3Smrg struct drm_v3d_mmap_bo *map = arg; 987ec681f3Smrg struct shim_bo *bo = drm_shim_bo_lookup(shim_fd, map->handle); 997ec681f3Smrg 1007ec681f3Smrg map->offset = drm_shim_bo_get_mmap_offset(shim_fd, bo); 1017ec681f3Smrg 1027ec681f3Smrg drm_shim_bo_put(bo); 1037ec681f3Smrg 1047ec681f3Smrg return 0; 1057ec681f3Smrg} 1067ec681f3Smrg 1077ec681f3Smrgstatic int 1087ec681f3Smrgv3d_ioctl_get_param(int fd, unsigned long request, void *arg) 1097ec681f3Smrg{ 1107ec681f3Smrg struct drm_v3d_get_param *gp = arg; 1117ec681f3Smrg static const uint32_t v3d42_reg_map[] = { 1127ec681f3Smrg [DRM_V3D_PARAM_V3D_UIFCFG] = 0x00000045, 1137ec681f3Smrg [DRM_V3D_PARAM_V3D_HUB_IDENT1] = 0x000e1124, 1147ec681f3Smrg [DRM_V3D_PARAM_V3D_HUB_IDENT2] = 0x00000100, 1157ec681f3Smrg [DRM_V3D_PARAM_V3D_HUB_IDENT3] = 0x00000e00, 1167ec681f3Smrg [DRM_V3D_PARAM_V3D_CORE0_IDENT0] = 0x04443356, 1177ec681f3Smrg [DRM_V3D_PARAM_V3D_CORE0_IDENT1] = 0x81001422, 1187ec681f3Smrg [DRM_V3D_PARAM_V3D_CORE0_IDENT2] = 0x40078121, 1197ec681f3Smrg }; 1207ec681f3Smrg 1217ec681f3Smrg switch (gp->param) { 1227ec681f3Smrg case DRM_V3D_PARAM_SUPPORTS_TFU: 1237ec681f3Smrg gp->value = 1; 1247ec681f3Smrg return 0; 1257ec681f3Smrg default: 1267ec681f3Smrg break; 1277ec681f3Smrg } 1287ec681f3Smrg 1297ec681f3Smrg if (gp->param < ARRAY_SIZE(v3d42_reg_map) && v3d42_reg_map[gp->param]) { 1307ec681f3Smrg gp->value = v3d42_reg_map[gp->param]; 1317ec681f3Smrg return 0; 1327ec681f3Smrg } 1337ec681f3Smrg 1347ec681f3Smrg fprintf(stderr, "Unknown DRM_IOCTL_V3D_GET_PARAM %d\n", gp->param); 1357ec681f3Smrg return -1; 1367ec681f3Smrg} 1377ec681f3Smrg 1387ec681f3Smrgstatic ioctl_fn_t driver_ioctls[] = { 1397ec681f3Smrg [DRM_V3D_SUBMIT_CL] = v3d_ioctl_noop, 1407ec681f3Smrg [DRM_V3D_SUBMIT_TFU] = v3d_ioctl_noop, 1417ec681f3Smrg [DRM_V3D_WAIT_BO] = v3d_ioctl_noop, 1427ec681f3Smrg [DRM_V3D_CREATE_BO] = v3d_ioctl_create_bo, 1437ec681f3Smrg [DRM_V3D_GET_PARAM] = v3d_ioctl_get_param, 1447ec681f3Smrg [DRM_V3D_GET_BO_OFFSET] = v3d_ioctl_get_bo_offset, 1457ec681f3Smrg [DRM_V3D_MMAP_BO] = v3d_ioctl_mmap_bo, 1467ec681f3Smrg}; 1477ec681f3Smrg 1487ec681f3Smrgvoid 1497ec681f3Smrgdrm_shim_driver_init(void) 1507ec681f3Smrg{ 1517ec681f3Smrg shim_device.bus_type = DRM_BUS_PLATFORM; 1527ec681f3Smrg shim_device.driver_name = "v3d"; 1537ec681f3Smrg shim_device.driver_ioctls = driver_ioctls; 1547ec681f3Smrg shim_device.driver_ioctl_count = ARRAY_SIZE(driver_ioctls); 1557ec681f3Smrg 1567ec681f3Smrg drm_shim_override_file("OF_FULLNAME=/rdb/v3d\n" 1577ec681f3Smrg "OF_COMPATIBLE_N=1\n" 1587ec681f3Smrg "OF_COMPATIBLE_0=brcm,7278-v3d\n", 1597ec681f3Smrg "/sys/dev/char/%d:%d/device/uevent", 1607ec681f3Smrg DRM_MAJOR, render_node_minor); 1617ec681f3Smrg} 162