1e88f27b3Smrg/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2e88f27b3Smrg 3e88f27b3Smrg/* 4e88f27b3Smrg * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org> 5e88f27b3Smrg * 6e88f27b3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7e88f27b3Smrg * copy of this software and associated documentation files (the "Software"), 8e88f27b3Smrg * to deal in the Software without restriction, including without limitation 9e88f27b3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10e88f27b3Smrg * and/or sell copies of the Software, and to permit persons to whom the 11e88f27b3Smrg * Software is furnished to do so, subject to the following conditions: 12e88f27b3Smrg * 13e88f27b3Smrg * The above copyright notice and this permission notice (including the next 14e88f27b3Smrg * paragraph) shall be included in all copies or substantial portions of the 15e88f27b3Smrg * Software. 16e88f27b3Smrg * 17e88f27b3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18e88f27b3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19e88f27b3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20e88f27b3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21e88f27b3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22e88f27b3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23e88f27b3Smrg * SOFTWARE. 24e88f27b3Smrg * 25e88f27b3Smrg * Authors: 26e88f27b3Smrg * Rob Clark <robclark@freedesktop.org> 27e88f27b3Smrg */ 28e88f27b3Smrg 29e88f27b3Smrg#include "msm_priv.h" 30e88f27b3Smrg 313f012e29Smrgstatic int query_param(struct fd_pipe *pipe, uint32_t param, 323f012e29Smrg uint64_t *value) 333f012e29Smrg{ 343f012e29Smrg struct msm_pipe *msm_pipe = to_msm_pipe(pipe); 353f012e29Smrg struct drm_msm_param req = { 363f012e29Smrg .pipe = msm_pipe->pipe, 373f012e29Smrg .param = param, 383f012e29Smrg }; 393f012e29Smrg int ret; 403f012e29Smrg 413f012e29Smrg ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_GET_PARAM, 423f012e29Smrg &req, sizeof(req)); 433f012e29Smrg if (ret) 443f012e29Smrg return ret; 453f012e29Smrg 463f012e29Smrg *value = req.value; 473f012e29Smrg 483f012e29Smrg return 0; 493f012e29Smrg} 50e88f27b3Smrg 51e88f27b3Smrgstatic int msm_pipe_get_param(struct fd_pipe *pipe, 52e88f27b3Smrg enum fd_param_id param, uint64_t *value) 53e88f27b3Smrg{ 54e88f27b3Smrg struct msm_pipe *msm_pipe = to_msm_pipe(pipe); 55e88f27b3Smrg switch(param) { 56e88f27b3Smrg case FD_DEVICE_ID: // XXX probably get rid of this.. 57e88f27b3Smrg case FD_GPU_ID: 58e88f27b3Smrg *value = msm_pipe->gpu_id; 59e88f27b3Smrg return 0; 60e88f27b3Smrg case FD_GMEM_SIZE: 61e88f27b3Smrg *value = msm_pipe->gmem; 62e88f27b3Smrg return 0; 63baaff307Smrg case FD_CHIP_ID: 64baaff307Smrg *value = msm_pipe->chip_id; 65baaff307Smrg return 0; 663f012e29Smrg case FD_MAX_FREQ: 673f012e29Smrg return query_param(pipe, MSM_PARAM_MAX_FREQ, value); 683f012e29Smrg case FD_TIMESTAMP: 693f012e29Smrg return query_param(pipe, MSM_PARAM_TIMESTAMP, value); 7000a23bdaSmrg case FD_NR_RINGS: 7100a23bdaSmrg return query_param(pipe, MSM_PARAM_NR_RINGS, value); 72e88f27b3Smrg default: 73e88f27b3Smrg ERROR_MSG("invalid param id: %d", param); 74e88f27b3Smrg return -1; 75e88f27b3Smrg } 76e88f27b3Smrg} 77e88f27b3Smrg 783f012e29Smrgstatic int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp, 793f012e29Smrg uint64_t timeout) 80e88f27b3Smrg{ 81e88f27b3Smrg struct fd_device *dev = pipe->dev; 82e88f27b3Smrg struct drm_msm_wait_fence req = { 83e88f27b3Smrg .fence = timestamp, 8400a23bdaSmrg .queueid = to_msm_pipe(pipe)->queue_id, 85e88f27b3Smrg }; 86e88f27b3Smrg int ret; 87e88f27b3Smrg 883f012e29Smrg get_abs_timeout(&req.timeout, timeout); 89e88f27b3Smrg 90e88f27b3Smrg ret = drmCommandWrite(dev->fd, DRM_MSM_WAIT_FENCE, &req, sizeof(req)); 91e88f27b3Smrg if (ret) { 92e88f27b3Smrg ERROR_MSG("wait-fence failed! %d (%s)", ret, strerror(errno)); 93e88f27b3Smrg return ret; 94e88f27b3Smrg } 95e88f27b3Smrg 96e88f27b3Smrg return 0; 97e88f27b3Smrg} 98e88f27b3Smrg 9900a23bdaSmrgstatic int open_submitqueue(struct fd_pipe *pipe, uint32_t prio) 10000a23bdaSmrg{ 10100a23bdaSmrg struct drm_msm_submitqueue req = { 10200a23bdaSmrg .flags = 0, 10300a23bdaSmrg .prio = prio, 10400a23bdaSmrg }; 10500a23bdaSmrg uint64_t nr_rings = 1; 10600a23bdaSmrg int ret; 10700a23bdaSmrg 10800a23bdaSmrg if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES) { 10900a23bdaSmrg to_msm_pipe(pipe)->queue_id = 0; 11000a23bdaSmrg return 0; 11100a23bdaSmrg } 11200a23bdaSmrg 11300a23bdaSmrg msm_pipe_get_param(pipe, FD_NR_RINGS, &nr_rings); 11400a23bdaSmrg 11500a23bdaSmrg req.prio = MIN2(req.prio, MAX2(nr_rings, 1) - 1); 11600a23bdaSmrg 11700a23bdaSmrg ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_NEW, 11800a23bdaSmrg &req, sizeof(req)); 11900a23bdaSmrg if (ret) { 12000a23bdaSmrg ERROR_MSG("could not create submitqueue! %d (%s)", ret, strerror(errno)); 12100a23bdaSmrg return ret; 12200a23bdaSmrg } 12300a23bdaSmrg 12400a23bdaSmrg to_msm_pipe(pipe)->queue_id = req.id; 12500a23bdaSmrg return 0; 12600a23bdaSmrg} 12700a23bdaSmrg 12800a23bdaSmrgstatic void close_submitqueue(struct fd_pipe *pipe, uint32_t queue_id) 12900a23bdaSmrg{ 13000a23bdaSmrg if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES) 13100a23bdaSmrg return; 13200a23bdaSmrg 13300a23bdaSmrg drmCommandWrite(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_CLOSE, 13400a23bdaSmrg &queue_id, sizeof(queue_id)); 13500a23bdaSmrg} 13600a23bdaSmrg 137e88f27b3Smrgstatic void msm_pipe_destroy(struct fd_pipe *pipe) 138e88f27b3Smrg{ 139e88f27b3Smrg struct msm_pipe *msm_pipe = to_msm_pipe(pipe); 14000a23bdaSmrg close_submitqueue(pipe, msm_pipe->queue_id); 1417cdc0497Smrg 1427cdc0497Smrg if (msm_pipe->suballoc_ring) { 1437cdc0497Smrg fd_ringbuffer_del(msm_pipe->suballoc_ring); 1447cdc0497Smrg msm_pipe->suballoc_ring = NULL; 1457cdc0497Smrg } 1467cdc0497Smrg 147e88f27b3Smrg free(msm_pipe); 148e88f27b3Smrg} 149e88f27b3Smrg 1503f012e29Smrgstatic const struct fd_pipe_funcs funcs = { 151e88f27b3Smrg .ringbuffer_new = msm_ringbuffer_new, 152e88f27b3Smrg .get_param = msm_pipe_get_param, 153e88f27b3Smrg .wait = msm_pipe_wait, 154e88f27b3Smrg .destroy = msm_pipe_destroy, 155e88f27b3Smrg}; 156e88f27b3Smrg 1573f012e29Smrgstatic uint64_t get_param(struct fd_pipe *pipe, uint32_t param) 158e88f27b3Smrg{ 1593f012e29Smrg uint64_t value; 1603f012e29Smrg int ret = query_param(pipe, param, &value); 161e88f27b3Smrg if (ret) { 162e88f27b3Smrg ERROR_MSG("get-param failed! %d (%s)", ret, strerror(errno)); 163e88f27b3Smrg return 0; 164e88f27b3Smrg } 1653f012e29Smrg return value; 166e88f27b3Smrg} 167e88f27b3Smrg 168e6188e58Smrgdrm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev, 16900a23bdaSmrg enum fd_pipe_id id, uint32_t prio) 170e88f27b3Smrg{ 171e88f27b3Smrg static const uint32_t pipe_id[] = { 172e88f27b3Smrg [FD_PIPE_3D] = MSM_PIPE_3D0, 173e88f27b3Smrg [FD_PIPE_2D] = MSM_PIPE_2D0, 174e88f27b3Smrg }; 175e88f27b3Smrg struct msm_pipe *msm_pipe = NULL; 176e88f27b3Smrg struct fd_pipe *pipe = NULL; 177e88f27b3Smrg 178e88f27b3Smrg msm_pipe = calloc(1, sizeof(*msm_pipe)); 179e88f27b3Smrg if (!msm_pipe) { 180e88f27b3Smrg ERROR_MSG("allocation failed"); 181e88f27b3Smrg goto fail; 182e88f27b3Smrg } 183e88f27b3Smrg 184e88f27b3Smrg pipe = &msm_pipe->base; 185e88f27b3Smrg pipe->funcs = &funcs; 186e88f27b3Smrg 1873f012e29Smrg /* initialize before get_param(): */ 1883f012e29Smrg pipe->dev = dev; 189e88f27b3Smrg msm_pipe->pipe = pipe_id[id]; 1903f012e29Smrg 1913f012e29Smrg /* these params should be supported since the first version of drm/msm: */ 1923f012e29Smrg msm_pipe->gpu_id = get_param(pipe, MSM_PARAM_GPU_ID); 1933f012e29Smrg msm_pipe->gmem = get_param(pipe, MSM_PARAM_GMEM_SIZE); 1943f012e29Smrg msm_pipe->chip_id = get_param(pipe, MSM_PARAM_CHIP_ID); 195e88f27b3Smrg 196e88f27b3Smrg if (! msm_pipe->gpu_id) 197e88f27b3Smrg goto fail; 198e88f27b3Smrg 199e88f27b3Smrg INFO_MSG("Pipe Info:"); 200e88f27b3Smrg INFO_MSG(" GPU-id: %d", msm_pipe->gpu_id); 201baaff307Smrg INFO_MSG(" Chip-id: 0x%08x", msm_pipe->chip_id); 202e88f27b3Smrg INFO_MSG(" GMEM size: 0x%08x", msm_pipe->gmem); 203e88f27b3Smrg 20400a23bdaSmrg if (open_submitqueue(pipe, prio)) 20500a23bdaSmrg goto fail; 20600a23bdaSmrg 207e88f27b3Smrg return pipe; 208e88f27b3Smrgfail: 209e88f27b3Smrg if (pipe) 210e88f27b3Smrg fd_pipe_del(pipe); 211e88f27b3Smrg return NULL; 212e88f27b3Smrg} 213