1 /* 2 * Copyright 2019 Advanced Micro Devices, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 19 * USE OR OTHER DEALINGS IN THE SOFTWARE. 20 * 21 * The above copyright notice and this permission notice (including the 22 * next paragraph) shall be included in all copies or substantial portions 23 * of the Software. 24 * 25 */ 26 27 #include "amdgpu.h" 28 #include "amdgpu_jpeg.h" 29 #include "amdgpu_pm.h" 30 #include "soc15d.h" 31 #include "soc15_common.h" 32 33 #define JPEG_IDLE_TIMEOUT msecs_to_jiffies(1000) 34 35 static void amdgpu_jpeg_idle_work_handler(struct work_struct *work); 36 37 int amdgpu_jpeg_sw_init(struct amdgpu_device *adev) 38 { 39 INIT_DELAYED_WORK(&adev->jpeg.idle_work, amdgpu_jpeg_idle_work_handler); 40 mutex_init(&adev->jpeg.jpeg_pg_lock); 41 atomic_set(&adev->jpeg.total_submission_cnt, 0); 42 43 return 0; 44 } 45 46 int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev) 47 { 48 int i; 49 50 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 51 if (adev->jpeg.harvest_config & (1 << i)) 52 continue; 53 54 amdgpu_ring_fini(&adev->jpeg.inst[i].ring_dec); 55 } 56 57 mutex_destroy(&adev->jpeg.jpeg_pg_lock); 58 59 return 0; 60 } 61 62 int amdgpu_jpeg_suspend(struct amdgpu_device *adev) 63 { 64 cancel_delayed_work_sync(&adev->jpeg.idle_work); 65 66 return 0; 67 } 68 69 int amdgpu_jpeg_resume(struct amdgpu_device *adev) 70 { 71 return 0; 72 } 73 74 static void amdgpu_jpeg_idle_work_handler(struct work_struct *work) 75 { 76 struct amdgpu_device *adev = 77 container_of(work, struct amdgpu_device, jpeg.idle_work.work); 78 unsigned int fences = 0; 79 unsigned int i; 80 81 for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 82 if (adev->jpeg.harvest_config & (1 << i)) 83 continue; 84 85 fences += amdgpu_fence_count_emitted(&adev->jpeg.inst[i].ring_dec); 86 } 87 88 if (!fences && !atomic_read(&adev->jpeg.total_submission_cnt)) 89 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG, 90 AMD_PG_STATE_GATE); 91 else 92 schedule_delayed_work(&adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT); 93 } 94 95 void amdgpu_jpeg_ring_begin_use(struct amdgpu_ring *ring) 96 { 97 struct amdgpu_device *adev = ring->adev; 98 99 atomic_inc(&adev->jpeg.total_submission_cnt); 100 cancel_delayed_work_sync(&adev->jpeg.idle_work); 101 102 mutex_lock(&adev->jpeg.jpeg_pg_lock); 103 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG, 104 AMD_PG_STATE_UNGATE); 105 mutex_unlock(&adev->jpeg.jpeg_pg_lock); 106 } 107 108 void amdgpu_jpeg_ring_end_use(struct amdgpu_ring *ring) 109 { 110 atomic_dec(&ring->adev->jpeg.total_submission_cnt); 111 schedule_delayed_work(&ring->adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT); 112 } 113 114 int amdgpu_jpeg_dec_ring_test_ring(struct amdgpu_ring *ring) 115 { 116 struct amdgpu_device *adev = ring->adev; 117 uint32_t tmp = 0; 118 unsigned i; 119 int r; 120 121 /* JPEG in SRIOV does not support direct register read/write */ 122 if (amdgpu_sriov_vf(adev)) 123 return 0; 124 125 WREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch, 0xCAFEDEAD); 126 r = amdgpu_ring_alloc(ring, 3); 127 if (r) 128 return r; 129 130 amdgpu_ring_write(ring, PACKET0(adev->jpeg.internal.jpeg_pitch, 0)); 131 amdgpu_ring_write(ring, 0xDEADBEEF); 132 amdgpu_ring_commit(ring); 133 134 for (i = 0; i < adev->usec_timeout; i++) { 135 tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch); 136 if (tmp == 0xDEADBEEF) 137 break; 138 udelay(1); 139 } 140 141 if (i >= adev->usec_timeout) 142 r = -ETIMEDOUT; 143 144 return r; 145 } 146 147 static int amdgpu_jpeg_dec_set_reg(struct amdgpu_ring *ring, uint32_t handle, 148 struct dma_fence **fence) 149 { 150 struct amdgpu_device *adev = ring->adev; 151 struct amdgpu_job *job; 152 struct amdgpu_ib *ib; 153 struct dma_fence *f = NULL; 154 const unsigned ib_size_dw = 16; 155 int i, r; 156 157 r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4, 158 AMDGPU_IB_POOL_DIRECT, &job); 159 if (r) 160 return r; 161 162 ib = &job->ibs[0]; 163 164 ib->ptr[0] = PACKETJ(adev->jpeg.internal.jpeg_pitch, 0, 0, 165 PACKETJ_TYPE0); 166 ib->ptr[1] = 0xDEADBEEF; 167 for (i = 2; i < 16; i += 2) { 168 ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6); 169 ib->ptr[i+1] = 0; 170 } 171 ib->length_dw = 16; 172 173 r = amdgpu_job_submit_direct(job, ring, &f); 174 if (r) 175 goto err; 176 177 if (fence) 178 *fence = dma_fence_get(f); 179 dma_fence_put(f); 180 181 return 0; 182 183 err: 184 amdgpu_job_free(job); 185 return r; 186 } 187 188 int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout) 189 { 190 struct amdgpu_device *adev = ring->adev; 191 uint32_t tmp = 0; 192 unsigned i; 193 struct dma_fence *fence = NULL; 194 long r = 0; 195 196 r = amdgpu_jpeg_dec_set_reg(ring, 1, &fence); 197 if (r) 198 goto error; 199 200 r = dma_fence_wait_timeout(fence, false, timeout); 201 if (r == 0) { 202 r = -ETIMEDOUT; 203 goto error; 204 } else if (r < 0) { 205 goto error; 206 } else { 207 r = 0; 208 } 209 if (!amdgpu_sriov_vf(adev)) { 210 for (i = 0; i < adev->usec_timeout; i++) { 211 tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch); 212 if (tmp == 0xDEADBEEF) 213 break; 214 udelay(1); 215 } 216 217 if (i >= adev->usec_timeout) 218 r = -ETIMEDOUT; 219 } 220 221 dma_fence_put(fence); 222 error: 223 return r; 224 } 225 226 int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev, 227 struct amdgpu_irq_src *source, 228 struct amdgpu_iv_entry *entry) 229 { 230 struct ras_common_if *ras_if = adev->jpeg.ras_if; 231 struct ras_dispatch_if ih_data = { 232 .entry = entry, 233 }; 234 235 if (!ras_if) 236 return 0; 237 238 ih_data.head = *ras_if; 239 amdgpu_ras_interrupt_dispatch(adev, &ih_data); 240 241 return 0; 242 } 243 244 int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev) 245 { 246 int err; 247 struct amdgpu_jpeg_ras *ras; 248 249 if (!adev->jpeg.ras) 250 return 0; 251 252 ras = adev->jpeg.ras; 253 err = amdgpu_ras_register_ras_block(adev, &ras->ras_block); 254 if (err) { 255 dev_err(adev->dev, "Failed to register jpeg ras block!\n"); 256 return err; 257 } 258 259 strcpy(ras->ras_block.ras_comm.name, "jpeg"); 260 ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__JPEG; 261 ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON; 262 adev->jpeg.ras_if = &ras->ras_block.ras_comm; 263 264 if (!ras->ras_block.ras_late_init) 265 ras->ras_block.ras_late_init = amdgpu_ras_block_late_init; 266 267 return 0; 268 } 269