1 1.1 riastrad /* $NetBSD: amdgpu_jpeg.c,v 1.2 2021/12/18 23:44:58 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2019 Advanced Micro Devices, Inc. 5 1.1 riastrad * All Rights Reserved. 6 1.1 riastrad * 7 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 8 1.1 riastrad * copy of this software and associated documentation files (the 9 1.1 riastrad * "Software"), to deal in the Software without restriction, including 10 1.1 riastrad * without limitation the rights to use, copy, modify, merge, publish, 11 1.1 riastrad * distribute, sub license, and/or sell copies of the Software, and to 12 1.1 riastrad * permit persons to whom the Software is furnished to do so, subject to 13 1.1 riastrad * the following conditions: 14 1.1 riastrad * 15 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 1.1 riastrad * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 1.1 riastrad * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 1.1 riastrad * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 1.1 riastrad * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 1.1 riastrad * 23 1.1 riastrad * The above copyright notice and this permission notice (including the 24 1.1 riastrad * next paragraph) shall be included in all copies or substantial portions 25 1.1 riastrad * of the Software. 26 1.1 riastrad * 27 1.1 riastrad */ 28 1.1 riastrad 29 1.1 riastrad #include <sys/cdefs.h> 30 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: amdgpu_jpeg.c,v 1.2 2021/12/18 23:44:58 riastradh Exp $"); 31 1.1 riastrad 32 1.1 riastrad #include "amdgpu.h" 33 1.1 riastrad #include "amdgpu_jpeg.h" 34 1.1 riastrad #include "amdgpu_pm.h" 35 1.1 riastrad #include "soc15d.h" 36 1.1 riastrad #include "soc15_common.h" 37 1.1 riastrad 38 1.1 riastrad #define JPEG_IDLE_TIMEOUT msecs_to_jiffies(1000) 39 1.1 riastrad 40 1.1 riastrad static void amdgpu_jpeg_idle_work_handler(struct work_struct *work); 41 1.1 riastrad 42 1.1 riastrad int amdgpu_jpeg_sw_init(struct amdgpu_device *adev) 43 1.1 riastrad { 44 1.1 riastrad INIT_DELAYED_WORK(&adev->jpeg.idle_work, amdgpu_jpeg_idle_work_handler); 45 1.1 riastrad 46 1.1 riastrad return 0; 47 1.1 riastrad } 48 1.1 riastrad 49 1.1 riastrad int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev) 50 1.1 riastrad { 51 1.1 riastrad int i; 52 1.1 riastrad 53 1.1 riastrad cancel_delayed_work_sync(&adev->jpeg.idle_work); 54 1.1 riastrad 55 1.1 riastrad for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 56 1.1 riastrad if (adev->jpeg.harvest_config & (1 << i)) 57 1.1 riastrad continue; 58 1.1 riastrad 59 1.1 riastrad amdgpu_ring_fini(&adev->jpeg.inst[i].ring_dec); 60 1.1 riastrad } 61 1.1 riastrad 62 1.1 riastrad return 0; 63 1.1 riastrad } 64 1.1 riastrad 65 1.1 riastrad int amdgpu_jpeg_suspend(struct amdgpu_device *adev) 66 1.1 riastrad { 67 1.1 riastrad cancel_delayed_work_sync(&adev->jpeg.idle_work); 68 1.1 riastrad 69 1.1 riastrad return 0; 70 1.1 riastrad } 71 1.1 riastrad 72 1.1 riastrad int amdgpu_jpeg_resume(struct amdgpu_device *adev) 73 1.1 riastrad { 74 1.1 riastrad return 0; 75 1.1 riastrad } 76 1.1 riastrad 77 1.1 riastrad static void amdgpu_jpeg_idle_work_handler(struct work_struct *work) 78 1.1 riastrad { 79 1.1 riastrad struct amdgpu_device *adev = 80 1.1 riastrad container_of(work, struct amdgpu_device, jpeg.idle_work.work); 81 1.1 riastrad unsigned int fences = 0; 82 1.1 riastrad unsigned int i; 83 1.1 riastrad 84 1.1 riastrad for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 85 1.1 riastrad if (adev->jpeg.harvest_config & (1 << i)) 86 1.1 riastrad continue; 87 1.1 riastrad 88 1.1 riastrad fences += amdgpu_fence_count_emitted(&adev->jpeg.inst[i].ring_dec); 89 1.1 riastrad } 90 1.1 riastrad 91 1.1 riastrad if (fences == 0) 92 1.1 riastrad amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG, 93 1.1 riastrad AMD_PG_STATE_GATE); 94 1.1 riastrad else 95 1.1 riastrad schedule_delayed_work(&adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT); 96 1.1 riastrad } 97 1.1 riastrad 98 1.1 riastrad void amdgpu_jpeg_ring_begin_use(struct amdgpu_ring *ring) 99 1.1 riastrad { 100 1.1 riastrad struct amdgpu_device *adev = ring->adev; 101 1.1 riastrad bool set_clocks = !cancel_delayed_work_sync(&adev->jpeg.idle_work); 102 1.1 riastrad 103 1.1 riastrad if (set_clocks) 104 1.1 riastrad amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG, 105 1.1 riastrad AMD_PG_STATE_UNGATE); 106 1.1 riastrad } 107 1.1 riastrad 108 1.1 riastrad void amdgpu_jpeg_ring_end_use(struct amdgpu_ring *ring) 109 1.1 riastrad { 110 1.1 riastrad schedule_delayed_work(&ring->adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT); 111 1.1 riastrad } 112 1.1 riastrad 113 1.1 riastrad int amdgpu_jpeg_dec_ring_test_ring(struct amdgpu_ring *ring) 114 1.1 riastrad { 115 1.1 riastrad struct amdgpu_device *adev = ring->adev; 116 1.1 riastrad uint32_t tmp = 0; 117 1.1 riastrad unsigned i; 118 1.1 riastrad int r; 119 1.1 riastrad 120 1.1 riastrad WREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch, 0xCAFEDEAD); 121 1.1 riastrad r = amdgpu_ring_alloc(ring, 3); 122 1.1 riastrad if (r) 123 1.1 riastrad return r; 124 1.1 riastrad 125 1.1 riastrad amdgpu_ring_write(ring, PACKET0(adev->jpeg.internal.jpeg_pitch, 0)); 126 1.1 riastrad amdgpu_ring_write(ring, 0xDEADBEEF); 127 1.1 riastrad amdgpu_ring_commit(ring); 128 1.1 riastrad 129 1.1 riastrad for (i = 0; i < adev->usec_timeout; i++) { 130 1.1 riastrad tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch); 131 1.1 riastrad if (tmp == 0xDEADBEEF) 132 1.1 riastrad break; 133 1.1 riastrad udelay(1); 134 1.1 riastrad } 135 1.1 riastrad 136 1.1 riastrad if (i >= adev->usec_timeout) 137 1.1 riastrad r = -ETIMEDOUT; 138 1.1 riastrad 139 1.1 riastrad return r; 140 1.1 riastrad } 141 1.1 riastrad 142 1.1 riastrad static int amdgpu_jpeg_dec_set_reg(struct amdgpu_ring *ring, uint32_t handle, 143 1.1 riastrad struct dma_fence **fence) 144 1.1 riastrad { 145 1.1 riastrad struct amdgpu_device *adev = ring->adev; 146 1.1 riastrad struct amdgpu_job *job; 147 1.1 riastrad struct amdgpu_ib *ib; 148 1.1 riastrad struct dma_fence *f = NULL; 149 1.1 riastrad const unsigned ib_size_dw = 16; 150 1.1 riastrad int i, r; 151 1.1 riastrad 152 1.1 riastrad r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); 153 1.1 riastrad if (r) 154 1.1 riastrad return r; 155 1.1 riastrad 156 1.1 riastrad ib = &job->ibs[0]; 157 1.1 riastrad 158 1.1 riastrad ib->ptr[0] = PACKETJ(adev->jpeg.internal.jpeg_pitch, 0, 0, PACKETJ_TYPE0); 159 1.1 riastrad ib->ptr[1] = 0xDEADBEEF; 160 1.1 riastrad for (i = 2; i < 16; i += 2) { 161 1.1 riastrad ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6); 162 1.1 riastrad ib->ptr[i+1] = 0; 163 1.1 riastrad } 164 1.1 riastrad ib->length_dw = 16; 165 1.1 riastrad 166 1.1 riastrad r = amdgpu_job_submit_direct(job, ring, &f); 167 1.1 riastrad if (r) 168 1.1 riastrad goto err; 169 1.1 riastrad 170 1.1 riastrad if (fence) 171 1.1 riastrad *fence = dma_fence_get(f); 172 1.1 riastrad dma_fence_put(f); 173 1.1 riastrad 174 1.1 riastrad return 0; 175 1.1 riastrad 176 1.1 riastrad err: 177 1.1 riastrad amdgpu_job_free(job); 178 1.1 riastrad return r; 179 1.1 riastrad } 180 1.1 riastrad 181 1.1 riastrad int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout) 182 1.1 riastrad { 183 1.1 riastrad struct amdgpu_device *adev = ring->adev; 184 1.1 riastrad uint32_t tmp = 0; 185 1.1 riastrad unsigned i; 186 1.1 riastrad struct dma_fence *fence = NULL; 187 1.1 riastrad long r = 0; 188 1.1 riastrad 189 1.1 riastrad r = amdgpu_jpeg_dec_set_reg(ring, 1, &fence); 190 1.1 riastrad if (r) 191 1.1 riastrad goto error; 192 1.1 riastrad 193 1.1 riastrad r = dma_fence_wait_timeout(fence, false, timeout); 194 1.1 riastrad if (r == 0) { 195 1.1 riastrad r = -ETIMEDOUT; 196 1.1 riastrad goto error; 197 1.1 riastrad } else if (r < 0) { 198 1.1 riastrad goto error; 199 1.1 riastrad } else { 200 1.1 riastrad r = 0; 201 1.1 riastrad } 202 1.1 riastrad 203 1.1 riastrad for (i = 0; i < adev->usec_timeout; i++) { 204 1.1 riastrad tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch); 205 1.1 riastrad if (tmp == 0xDEADBEEF) 206 1.1 riastrad break; 207 1.1 riastrad udelay(1); 208 1.1 riastrad } 209 1.1 riastrad 210 1.1 riastrad if (i >= adev->usec_timeout) 211 1.1 riastrad r = -ETIMEDOUT; 212 1.1 riastrad 213 1.1 riastrad dma_fence_put(fence); 214 1.1 riastrad error: 215 1.1 riastrad return r; 216 1.1 riastrad } 217