Pull drm fixes from Dave Airlie: "This has a bunch of nouveau fixes, as Ben has been hibernating and has lots of small fixes for lots of bugs across nouveau. Radeon has one major fix for hdmi/dp audio regression that is larger than Alex would like, but seems to fix up a fair few bugs, along with some misc fixes. And a few msm fixes, one of which is also a bit large. But nothing in here seems insane or crazy for this stage, just more than I'd like" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (33 commits) drm/msm/mdp5: release SMB (shared memory blocks) in various cases drm/msm: change to uninterruptible wait in atomic commit drm/msm: mdp4: Fix drm_framebuffer dereference crash drm/msm: fix msm_gem_prime_get_sg_table() drm/amdgpu: add new parameter to seperate map and unmap drm/amdgpu: hdp_flush is not needed for inside IB drm/amdgpu: different emit_ib for gfx and compute drm/amdgpu: information leak in amdgpu_info_ioctl() drm/amdgpu: clean up init sequence for failures drm/radeon/combios: add some validation of lvds values drm/radeon: rework audio modeset to handle non-audio hdmi features drm/radeon: rework audio detect (v4) drm/amdgpu: Drop drm/ prefix for including drm.h in amdgpu_drm.h drm/radeon: Drop drm/ prefix for including drm.h in radeon_drm.h drm/nouveau/nouveau/ttm: fix tiled system memory with Maxwell drm/nouveau/kms/nv50-: guard against enabling cursor on disabled heads drm/nouveau/fbcon/g80: reduce PUSH_SPACE alloc, fire ring on accel init drm/nouveau/fbcon/gf100-: reduce RING_SPACE allocation drm/nouveau/fbcon/nv11-: correctly account for ring space usage drm/nouveau/bios: add proper support for opcode 0x59 ...
Unified · Split
| @@ -1866,6 +1866,12 @@ typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t); · 1865 unmodified lines | ||
| 1866 | 1866 | typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t); |
| 1867 | 1867 | typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t); |
| 1868 | 1868 | |
| 1869 | +struct amdgpu_ip_block_status { | |
| 1870 | + bool valid; | |
| 1871 | + bool sw; | |
| 1872 | + bool hw; | |
| 1873 | +}; | |
| 1874 | + | |
| 1869 | 1875 | struct amdgpu_device { |
| 1870 | 1876 | struct device *dev; |
| 1871 | 1877 | struct drm_device *ddev; |
| @@ -2008,7 +2014,7 @@ struct amdgpu_device { · 136 unmodified lines | ||
| 2008 | 2014 | |
| 2009 | 2015 | const struct amdgpu_ip_block_version *ip_blocks; |
| 2010 | 2016 | int num_ip_blocks; |
| 2011 | − bool *ip_block_enabled; | |
| 2017 | + struct amdgpu_ip_block_status *ip_block_status; | |
| 2012 | 2018 | struct mutex mn_lock; |
| 2013 | 2019 | DECLARE_HASHTABLE(mn_hash, 7); |
| 2014 | 2020 | |
| @@ -1191,8 +1191,9 @@ static int amdgpu_early_init(struct amdgpu_device *adev) · 1190 unmodified lines | ||
| 1191 | 1191 | return -EINVAL; |
| 1192 | 1192 | } |
| 1193 | 1193 | |
| 1194 | − adev->ip_block_enabled = kcalloc(adev->num_ip_blocks, sizeof(bool), GFP_KERNEL); | |
| 1195 | − if (adev->ip_block_enabled == NULL) | |
| 1194 | + adev->ip_block_status = kcalloc(adev->num_ip_blocks, | |
| 1195 | + sizeof(struct amdgpu_ip_block_status), GFP_KERNEL); | |
| 1196 | + if (adev->ip_block_status == NULL) | |
| 1196 | 1197 | return -ENOMEM; |
| 1197 | 1198 | |
| 1198 | 1199 | if (adev->ip_blocks == NULL) { |
| @@ -1203,18 +1204,18 @@ static int amdgpu_early_init(struct amdgpu_device *adev) · 4 unmodified lines | ||
| 1203 | 1204 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 1204 | 1205 | if ((amdgpu_ip_block_mask & (1 << i)) == 0) { |
| 1205 | 1206 | DRM_ERROR("disabled ip block: %d\n", i); |
| 1206 | − adev->ip_block_enabled[i] = false; | |
| 1207 | + adev->ip_block_status[i].valid = false; | |
| 1207 | 1208 | } else { |
| 1208 | 1209 | if (adev->ip_blocks[i].funcs->early_init) { |
| 1209 | 1210 | r = adev->ip_blocks[i].funcs->early_init((void *)adev); |
| 1210 | 1211 | if (r == -ENOENT) |
| 1211 | − adev->ip_block_enabled[i] = false; | |
| 1212 | + adev->ip_block_status[i].valid = false; | |
| 1212 | 1213 | else if (r) |
| 1213 | 1214 | return r; |
| 1214 | 1215 | else |
| 1215 | − adev->ip_block_enabled[i] = true; | |
| 1216 | + adev->ip_block_status[i].valid = true; | |
| 1216 | 1217 | } else { |
| 1217 | − adev->ip_block_enabled[i] = true; | |
| 1218 | + adev->ip_block_status[i].valid = true; | |
| 1218 | 1219 | } |
| 1219 | 1220 | } |
| 1220 | 1221 | } |
| @@ -1227,11 +1228,12 @@ static int amdgpu_init(struct amdgpu_device *adev) · 6 unmodified lines | ||
| 1227 | 1228 | int i, r; |
| 1228 | 1229 | |
| 1229 | 1230 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 1230 | − if (!adev->ip_block_enabled[i]) | |
| 1231 | + if (!adev->ip_block_status[i].valid) | |
| 1231 | 1232 | continue; |
| 1232 | 1233 | r = adev->ip_blocks[i].funcs->sw_init((void *)adev); |
| 1233 | 1234 | if (r) |
| 1234 | 1235 | return r; |
| 1236 | + adev->ip_block_status[i].sw = true; | |
| 1235 | 1237 | /* need to do gmc hw init early so we can allocate gpu mem */ |
| 1236 | 1238 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { |
| 1237 | 1239 | r = amdgpu_vram_scratch_init(adev); |
| @@ -1243,11 +1245,12 @@ static int amdgpu_init(struct amdgpu_device *adev) · 5 unmodified lines | ||
| 1243 | 1245 | r = amdgpu_wb_init(adev); |
| 1244 | 1246 | if (r) |
| 1245 | 1247 | return r; |
| 1248 | + adev->ip_block_status[i].hw = true; | |
| 1246 | 1249 | } |
| 1247 | 1250 | } |
| 1248 | 1251 | |
| 1249 | 1252 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 1250 | − if (!adev->ip_block_enabled[i]) | |
| 1253 | + if (!adev->ip_block_status[i].sw) | |
| 1251 | 1254 | continue; |
| 1252 | 1255 | /* gmc hw init is done early */ |
| 1253 | 1256 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) |
| @@ -1255,6 +1258,7 @@ static int amdgpu_init(struct amdgpu_device *adev) · 1 unmodified line | ||
| 1255 | 1258 | r = adev->ip_blocks[i].funcs->hw_init((void *)adev); |
| 1256 | 1259 | if (r) |
| 1257 | 1260 | return r; |
| 1261 | + adev->ip_block_status[i].hw = true; | |
| 1258 | 1262 | } |
| 1259 | 1263 | |
| 1260 | 1264 | return 0; |
| @@ -1265,7 +1269,7 @@ static int amdgpu_late_init(struct amdgpu_device *adev) · 4 unmodified lines | ||
| 1265 | 1269 | int i = 0, r; |
| 1266 | 1270 | |
| 1267 | 1271 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 1268 | − if (!adev->ip_block_enabled[i]) | |
| 1272 | + if (!adev->ip_block_status[i].valid) | |
| 1269 | 1273 | continue; |
| 1270 | 1274 | /* enable clockgating to save power */ |
| 1271 | 1275 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, |
| @@ -1287,7 +1291,7 @@ static int amdgpu_fini(struct amdgpu_device *adev) · 15 unmodified lines | ||
| 1287 | 1291 | int i, r; |
| 1288 | 1292 | |
| 1289 | 1293 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { |
| 1290 | − if (!adev->ip_block_enabled[i]) | |
| 1294 | + if (!adev->ip_block_status[i].hw) | |
| 1291 | 1295 | continue; |
| 1292 | 1296 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { |
| 1293 | 1297 | amdgpu_wb_fini(adev); |
| @@ -1300,14 +1304,16 @@ static int amdgpu_fini(struct amdgpu_device *adev) · 6 unmodified lines | ||
| 1300 | 1304 | return r; |
| 1301 | 1305 | r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); |
| 1302 | 1306 | /* XXX handle errors */ |
| 1307 | + adev->ip_block_status[i].hw = false; | |
| 1303 | 1308 | } |
| 1304 | 1309 | |
| 1305 | 1310 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { |
| 1306 | − if (!adev->ip_block_enabled[i]) | |
| 1311 | + if (!adev->ip_block_status[i].sw) | |
| 1307 | 1312 | continue; |
| 1308 | 1313 | r = adev->ip_blocks[i].funcs->sw_fini((void *)adev); |
| 1309 | 1314 | /* XXX handle errors */ |
| 1310 | − adev->ip_block_enabled[i] = false; | |
| 1315 | + adev->ip_block_status[i].sw = false; | |
| 1316 | + adev->ip_block_status[i].valid = false; | |
| 1311 | 1317 | } |
| 1312 | 1318 | |
| 1313 | 1319 | return 0; |
| @@ -1318,7 +1324,7 @@ static int amdgpu_suspend(struct amdgpu_device *adev) · 4 unmodified lines | ||
| 1318 | 1324 | int i, r; |
| 1319 | 1325 | |
| 1320 | 1326 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { |
| 1321 | − if (!adev->ip_block_enabled[i]) | |
| 1327 | + if (!adev->ip_block_status[i].valid) | |
| 1322 | 1328 | continue; |
| 1323 | 1329 | /* ungate blocks so that suspend can properly shut them down */ |
| 1324 | 1330 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, |
| @@ -1336,7 +1342,7 @@ static int amdgpu_resume(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 1336 | 1342 | int i, r; |
| 1337 | 1343 | |
| 1338 | 1344 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 1339 | − if (!adev->ip_block_enabled[i]) | |
| 1345 | + if (!adev->ip_block_status[i].valid) | |
| 1340 | 1346 | continue; |
| 1341 | 1347 | r = adev->ip_blocks[i].funcs->resume(adev); |
| 1342 | 1348 | if (r) |
| @@ -1582,8 +1588,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) · 239 unmodified lines | ||
| 1582 | 1588 | amdgpu_fence_driver_fini(adev); |
| 1583 | 1589 | amdgpu_fbdev_fini(adev); |
| 1584 | 1590 | r = amdgpu_fini(adev); |
| 1585 | − kfree(adev->ip_block_enabled); | |
| 1586 | − adev->ip_block_enabled = NULL; | |
| 1591 | + kfree(adev->ip_block_status); | |
| 1592 | + adev->ip_block_status = NULL; | |
| 1587 | 1593 | adev->accel_working = false; |
| 1588 | 1594 | /* free i2c buses */ |
| 1589 | 1595 | amdgpu_i2c_fini(adev); |
| @@ -449,7 +449,7 @@ out: · 448 unmodified lines | ||
| 449 | 449 | * vital here, so they are not reported back to userspace. |
| 450 | 450 | */ |
| 451 | 451 | static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, |
| 452 | − struct amdgpu_bo_va *bo_va) | |
| 452 | + struct amdgpu_bo_va *bo_va, uint32_t operation) | |
| 453 | 453 | { |
| 454 | 454 | struct ttm_validate_buffer tv, *entry; |
| 455 | 455 | struct amdgpu_bo_list_entry *vm_bos; |
| @@ -485,7 +485,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, · 29 unmodified lines | ||
| 485 | 485 | if (r) |
| 486 | 486 | goto error_unlock; |
| 487 | 487 | |
| 488 | − r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem); | |
| 488 | + | |
| 489 | + if (operation == AMDGPU_VA_OP_MAP) | |
| 490 | + r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem); | |
| 489 | 491 | |
| 490 | 492 | error_unlock: |
| 491 | 493 | mutex_unlock(&bo_va->vm->mutex); |
| @@ -580,7 +582,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, · 88 unmodified lines | ||
| 580 | 582 | } |
| 581 | 583 | |
| 582 | 584 | if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE)) |
| 583 | − amdgpu_gem_va_update_vm(adev, bo_va); | |
| 585 | + amdgpu_gem_va_update_vm(adev, bo_va, args->operation); | |
| 584 | 586 | |
| 585 | 587 | drm_gem_object_unreference_unlocked(gobj); |
| 586 | 588 | return r; |
| @@ -180,16 +180,16 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, · 179 unmodified lines | ||
| 180 | 180 | if (vm) { |
| 181 | 181 | /* do context switch */ |
| 182 | 182 | amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update); |
| 183 | − } | |
| 184 | 183 | |
| 185 | − if (vm && ring->funcs->emit_gds_switch) | |
| 186 | − amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, | |
| 187 | − ib->gds_base, ib->gds_size, | |
| 188 | − ib->gws_base, ib->gws_size, | |
| 189 | − ib->oa_base, ib->oa_size); | |
| 184 | + if (ring->funcs->emit_gds_switch) | |
| 185 | + amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, | |
| 186 | + ib->gds_base, ib->gds_size, | |
| 187 | + ib->gws_base, ib->gws_size, | |
| 188 | + ib->oa_base, ib->oa_size); | |
| 190 | 189 | |
| 191 | − if (ring->funcs->emit_hdp_flush) | |
| 192 | − amdgpu_ring_emit_hdp_flush(ring); | |
| 190 | + if (ring->funcs->emit_hdp_flush) | |
| 191 | + amdgpu_ring_emit_hdp_flush(ring); | |
| 192 | + } | |
| 193 | 193 | |
| 194 | 194 | old_ctx = ring->current_ctx; |
| 195 | 195 | for (i = 0; i < num_ibs; ++i) { |
| @@ -235,7 +235,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file · 234 unmodified lines | ||
| 235 | 235 | |
| 236 | 236 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 237 | 237 | if (adev->ip_blocks[i].type == type && |
| 238 | − adev->ip_block_enabled[i]) { | |
| 238 | + adev->ip_block_status[i].valid) { | |
| 239 | 239 | ip.hw_ip_version_major = adev->ip_blocks[i].major; |
| 240 | 240 | ip.hw_ip_version_minor = adev->ip_blocks[i].minor; |
| 241 | 241 | ip.capabilities_flags = 0; |
| @@ -274,7 +274,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file · 32 unmodified lines | ||
| 274 | 274 | |
| 275 | 275 | for (i = 0; i < adev->num_ip_blocks; i++) |
| 276 | 276 | if (adev->ip_blocks[i].type == type && |
| 277 | − adev->ip_block_enabled[i] && | |
| 277 | + adev->ip_block_status[i].valid && | |
| 278 | 278 | count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT) |
| 279 | 279 | count++; |
| 280 | 280 | |
| @@ -416,7 +416,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file · 135 unmodified lines | ||
| 416 | 416 | return n ? -EFAULT : 0; |
| 417 | 417 | } |
| 418 | 418 | case AMDGPU_INFO_DEV_INFO: { |
| 419 | − struct drm_amdgpu_info_device dev_info; | |
| 419 | + struct drm_amdgpu_info_device dev_info = {}; | |
| 420 | 420 | struct amdgpu_cu_info cu_info; |
| 421 | 421 | |
| 422 | 422 | dev_info.device_id = dev->pdev->device; |
| @@ -2561,7 +2561,7 @@ static bool gfx_v7_0_ring_emit_semaphore(struct amdgpu_ring *ring, · 2560 unmodified lines | ||
| 2561 | 2561 | * sheduling on the ring. This function schedules the IB |
| 2562 | 2562 | * on the gfx ring for execution by the GPU. |
| 2563 | 2563 | */ |
| 2564 | −static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, | |
| 2564 | +static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, | |
| 2565 | 2565 | struct amdgpu_ib *ib) |
| 2566 | 2566 | { |
| 2567 | 2567 | bool need_ctx_switch = ring->current_ctx != ib->ctx; |
| @@ -2569,15 +2569,10 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, · 1 unmodified line | ||
| 2569 | 2569 | u32 next_rptr = ring->wptr + 5; |
| 2570 | 2570 | |
| 2571 | 2571 | /* drop the CE preamble IB for the same context */ |
| 2572 | − if ((ring->type == AMDGPU_RING_TYPE_GFX) && | |
| 2573 | − (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && | |
| 2574 | − !need_ctx_switch) | |
| 2572 | + if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch) | |
| 2575 | 2573 | return; |
| 2576 | 2574 | |
| 2577 | − if (ring->type == AMDGPU_RING_TYPE_COMPUTE) | |
| 2578 | − control |= INDIRECT_BUFFER_VALID; | |
| 2579 | − | |
| 2580 | − if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) | |
| 2575 | + if (need_ctx_switch) | |
| 2581 | 2576 | next_rptr += 2; |
| 2582 | 2577 | |
| 2583 | 2578 | next_rptr += 4; |
| @@ -2588,7 +2583,7 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, · 4 unmodified lines | ||
| 2588 | 2583 | amdgpu_ring_write(ring, next_rptr); |
| 2589 | 2584 | |
| 2590 | 2585 | /* insert SWITCH_BUFFER packet before first IB in the ring frame */ |
| 2591 | − if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { | |
| 2586 | + if (need_ctx_switch) { | |
| 2592 | 2587 | amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); |
| 2593 | 2588 | amdgpu_ring_write(ring, 0); |
| 2594 | 2589 | } |
| @@ -2611,6 +2606,35 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, · 16 unmodified lines | ||
| 2611 | 2606 | amdgpu_ring_write(ring, control); |
| 2612 | 2607 | } |
| 2613 | 2608 | |
| 2609 | +static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring, | |
| 2610 | + struct amdgpu_ib *ib) | |
| 2611 | +{ | |
| 2612 | + u32 header, control = 0; | |
| 2613 | + u32 next_rptr = ring->wptr + 5; | |
| 2614 | + | |
| 2615 | + control |= INDIRECT_BUFFER_VALID; | |
| 2616 | + next_rptr += 4; | |
| 2617 | + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); | |
| 2618 | + amdgpu_ring_write(ring, WRITE_DATA_DST_SEL(5) | WR_CONFIRM); | |
| 2619 | + amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); | |
| 2620 | + amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); | |
| 2621 | + amdgpu_ring_write(ring, next_rptr); | |
| 2622 | + | |
| 2623 | + header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); | |
| 2624 | + | |
| 2625 | + control |= ib->length_dw | | |
| 2626 | + (ib->vm ? (ib->vm->ids[ring->idx].id << 24) : 0); | |
| 2627 | + | |
| 2628 | + amdgpu_ring_write(ring, header); | |
| 2629 | + amdgpu_ring_write(ring, | |
| 2630 | +#ifdef __BIG_ENDIAN | |
| 2631 | + (2 << 0) | | |
| 2632 | +#endif | |
| 2633 | + (ib->gpu_addr & 0xFFFFFFFC)); | |
| 2634 | + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); | |
| 2635 | + amdgpu_ring_write(ring, control); | |
| 2636 | +} | |
| 2637 | + | |
| 2614 | 2638 | /** |
| 2615 | 2639 | * gfx_v7_0_ring_test_ib - basic ring IB test |
| 2616 | 2640 | * |
| @@ -5555,7 +5579,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { · 2938 unmodified lines | ||
| 5555 | 5579 | .get_wptr = gfx_v7_0_ring_get_wptr_gfx, |
| 5556 | 5580 | .set_wptr = gfx_v7_0_ring_set_wptr_gfx, |
| 5557 | 5581 | .parse_cs = NULL, |
| 5558 | − .emit_ib = gfx_v7_0_ring_emit_ib, | |
| 5582 | + .emit_ib = gfx_v7_0_ring_emit_ib_gfx, | |
| 5559 | 5583 | .emit_fence = gfx_v7_0_ring_emit_fence_gfx, |
| 5560 | 5584 | .emit_semaphore = gfx_v7_0_ring_emit_semaphore, |
| 5561 | 5585 | .emit_vm_flush = gfx_v7_0_ring_emit_vm_flush, |
| @@ -5571,7 +5595,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { · 9 unmodified lines | ||
| 5571 | 5595 | .get_wptr = gfx_v7_0_ring_get_wptr_compute, |
| 5572 | 5596 | .set_wptr = gfx_v7_0_ring_set_wptr_compute, |
| 5573 | 5597 | .parse_cs = NULL, |
| 5574 | − .emit_ib = gfx_v7_0_ring_emit_ib, | |
| 5598 | + .emit_ib = gfx_v7_0_ring_emit_ib_compute, | |
| 5575 | 5599 | .emit_fence = gfx_v7_0_ring_emit_fence_compute, |
| 5576 | 5600 | .emit_semaphore = gfx_v7_0_ring_emit_semaphore, |
| 5577 | 5601 | .emit_vm_flush = gfx_v7_0_ring_emit_vm_flush, |
| @@ -3753,7 +3753,7 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) · 3752 unmodified lines | ||
| 3753 | 3753 | amdgpu_ring_write(ring, 0x20); /* poll interval */ |
| 3754 | 3754 | } |
| 3755 | 3755 | |
| 3756 | −static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, | |
| 3756 | +static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, | |
| 3757 | 3757 | struct amdgpu_ib *ib) |
| 3758 | 3758 | { |
| 3759 | 3759 | bool need_ctx_switch = ring->current_ctx != ib->ctx; |
| @@ -3761,15 +3761,10 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, · 1 unmodified line | ||
| 3761 | 3761 | u32 next_rptr = ring->wptr + 5; |
| 3762 | 3762 | |
| 3763 | 3763 | /* drop the CE preamble IB for the same context */ |
| 3764 | − if ((ring->type == AMDGPU_RING_TYPE_GFX) && | |
| 3765 | − (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && | |
| 3766 | − !need_ctx_switch) | |
| 3764 | + if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch) | |
| 3767 | 3765 | return; |
| 3768 | 3766 | |
| 3769 | − if (ring->type == AMDGPU_RING_TYPE_COMPUTE) | |
| 3770 | − control |= INDIRECT_BUFFER_VALID; | |
| 3771 | − | |
| 3772 | − if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) | |
| 3767 | + if (need_ctx_switch) | |
| 3773 | 3768 | next_rptr += 2; |
| 3774 | 3769 | |
| 3775 | 3770 | next_rptr += 4; |
| @@ -3780,7 +3775,7 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, · 4 unmodified lines | ||
| 3780 | 3775 | amdgpu_ring_write(ring, next_rptr); |
| 3781 | 3776 | |
| 3782 | 3777 | /* insert SWITCH_BUFFER packet before first IB in the ring frame */ |
| 3783 | − if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { | |
| 3778 | + if (need_ctx_switch) { | |
| 3784 | 3779 | amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); |
| 3785 | 3780 | amdgpu_ring_write(ring, 0); |
| 3786 | 3781 | } |
| @@ -3803,6 +3798,36 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, · 16 unmodified lines | ||
| 3803 | 3798 | amdgpu_ring_write(ring, control); |
| 3804 | 3799 | } |
| 3805 | 3800 | |
| 3801 | +static void gfx_v8_0_ring_emit_ib_compute(struct amdgpu_ring *ring, | |
| 3802 | + struct amdgpu_ib *ib) | |
| 3803 | +{ | |
| 3804 | + u32 header, control = 0; | |
| 3805 | + u32 next_rptr = ring->wptr + 5; | |
| 3806 | + | |
| 3807 | + control |= INDIRECT_BUFFER_VALID; | |
| 3808 | + | |
| 3809 | + next_rptr += 4; | |
| 3810 | + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); | |
| 3811 | + amdgpu_ring_write(ring, WRITE_DATA_DST_SEL(5) | WR_CONFIRM); | |
| 3812 | + amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); | |
| 3813 | + amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); | |
| 3814 | + amdgpu_ring_write(ring, next_rptr); | |
| 3815 | + | |
| 3816 | + header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); | |
| 3817 | + | |
| 3818 | + control |= ib->length_dw | | |
| 3819 | + (ib->vm ? (ib->vm->ids[ring->idx].id << 24) : 0); | |
| 3820 | + | |
| 3821 | + amdgpu_ring_write(ring, header); | |
| 3822 | + amdgpu_ring_write(ring, | |
| 3823 | +#ifdef __BIG_ENDIAN | |
| 3824 | + (2 << 0) | | |
| 3825 | +#endif | |
| 3826 | + (ib->gpu_addr & 0xFFFFFFFC)); | |
| 3827 | + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); | |
| 3828 | + amdgpu_ring_write(ring, control); | |
| 3829 | +} | |
| 3830 | + | |
| 3806 | 3831 | static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, |
| 3807 | 3832 | u64 seq, unsigned flags) |
| 3808 | 3833 | { |
| @@ -4224,7 +4249,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { · 415 unmodified lines | ||
| 4224 | 4249 | .get_wptr = gfx_v8_0_ring_get_wptr_gfx, |
| 4225 | 4250 | .set_wptr = gfx_v8_0_ring_set_wptr_gfx, |
| 4226 | 4251 | .parse_cs = NULL, |
| 4227 | − .emit_ib = gfx_v8_0_ring_emit_ib, | |
| 4252 | + .emit_ib = gfx_v8_0_ring_emit_ib_gfx, | |
| 4228 | 4253 | .emit_fence = gfx_v8_0_ring_emit_fence_gfx, |
| 4229 | 4254 | .emit_semaphore = gfx_v8_0_ring_emit_semaphore, |
| 4230 | 4255 | .emit_vm_flush = gfx_v8_0_ring_emit_vm_flush, |
| @@ -4240,7 +4265,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { · 9 unmodified lines | ||
| 4240 | 4265 | .get_wptr = gfx_v8_0_ring_get_wptr_compute, |
| 4241 | 4266 | .set_wptr = gfx_v8_0_ring_set_wptr_compute, |
| 4242 | 4267 | .parse_cs = NULL, |
| 4243 | − .emit_ib = gfx_v8_0_ring_emit_ib, | |
| 4268 | + .emit_ib = gfx_v8_0_ring_emit_ib_compute, | |
| 4244 | 4269 | .emit_fence = gfx_v8_0_ring_emit_fence_compute, |
| 4245 | 4270 | .emit_semaphore = gfx_v8_0_ring_emit_semaphore, |
| 4246 | 4271 | .emit_vm_flush = gfx_v8_0_ring_emit_vm_flush, |
| @@ -220,13 +220,15 @@ static int mdp4_plane_mode_set(struct drm_plane *plane, · 219 unmodified lines | ||
| 220 | 220 | uint32_t op_mode = 0; |
| 221 | 221 | uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT; |
| 222 | 222 | uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT; |
| 223 | − enum mdp4_frame_format frame_type = mdp4_get_frame_format(fb); | |
| 223 | + enum mdp4_frame_format frame_type; | |
| 224 | 224 | |
| 225 | 225 | if (!(crtc && fb)) { |
| 226 | 226 | DBG("%s: disabled!", mdp4_plane->name); |
| 227 | 227 | return 0; |
| 228 | 228 | } |
| 229 | 229 | |
| 230 | + frame_type = mdp4_get_frame_format(fb); | |
| 231 | + | |
| 230 | 232 | /* src values are in Q16 fixed point, convert to integer: */ |
| 231 | 233 | src_x = src_x >> 16; |
| 232 | 234 | src_y = src_y >> 16; |
| @@ -76,7 +76,20 @@ static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *st · 75 unmodified lines | ||
| 76 | 76 | |
| 77 | 77 | static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) |
| 78 | 78 | { |
| 79 | + int i; | |
| 79 | 80 | struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); |
| 81 | + int nplanes = mdp5_kms->dev->mode_config.num_total_plane; | |
| 82 | + | |
| 83 | + for (i = 0; i < nplanes; i++) { | |
| 84 | + struct drm_plane *plane = state->planes[i]; | |
| 85 | + struct drm_plane_state *plane_state = state->plane_states[i]; | |
| 86 | + | |
| 87 | + if (!plane) | |
| 88 | + continue; | |
| 89 | + | |
| 90 | + mdp5_plane_complete_commit(plane, plane_state); | |
| 91 | + } | |
| 92 | + | |
| 80 | 93 | mdp5_disable(mdp5_kms); |
| 81 | 94 | } |
| 82 | 95 | |
| @@ -227,6 +227,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane, · 226 unmodified lines | ||
| 227 | 227 | struct drm_mode_object *obj); |
| 228 | 228 | uint32_t mdp5_plane_get_flush(struct drm_plane *plane); |
| 229 | 229 | void mdp5_plane_complete_flip(struct drm_plane *plane); |
| 230 | +void mdp5_plane_complete_commit(struct drm_plane *plane, | |
| 231 | + struct drm_plane_state *state); | |
| 230 | 232 | enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane); |
| 231 | 233 | struct drm_plane *mdp5_plane_init(struct drm_device *dev, |
| 232 | 234 | enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset); |
| @@ -31,8 +31,6 @@ struct mdp5_plane { · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | uint32_t nformats; |
| 33 | 33 | uint32_t formats[32]; |
| 34 | − | |
| 35 | − bool enabled; | |
| 36 | 34 | }; |
| 37 | 35 | #define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base) |
| 38 | 36 | |
| @@ -56,22 +54,6 @@ static bool plane_enabled(struct drm_plane_state *state) · 17 unmodified lines | ||
| 56 | 54 | return state->fb && state->crtc; |
| 57 | 55 | } |
| 58 | 56 | |
| 59 | −static int mdp5_plane_disable(struct drm_plane *plane) | |
| 60 | −{ | |
| 61 | − struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); | |
| 62 | − struct mdp5_kms *mdp5_kms = get_kms(plane); | |
| 63 | − enum mdp5_pipe pipe = mdp5_plane->pipe; | |
| 64 | − | |
| 65 | − DBG("%s: disable", mdp5_plane->name); | |
| 66 | − | |
| 67 | − if (mdp5_kms) { | |
| 68 | − /* Release the memory we requested earlier from the SMP: */ | |
| 69 | − mdp5_smp_release(mdp5_kms->smp, pipe); | |
| 70 | − } | |
| 71 | − | |
| 72 | − return 0; | |
| 73 | −} | |
| 74 | − | |
| 75 | 57 | static void mdp5_plane_destroy(struct drm_plane *plane) |
| 76 | 58 | { |
| 77 | 59 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); |
| @@ -224,7 +206,6 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, · 146 unmodified lines | ||
| 224 | 206 | |
| 225 | 207 | if (!plane_enabled(state)) { |
| 226 | 208 | to_mdp5_plane_state(state)->pending = true; |
| 227 | − mdp5_plane_disable(plane); | |
| 228 | 209 | } else if (to_mdp5_plane_state(state)->mode_changed) { |
| 229 | 210 | int ret; |
| 230 | 211 | to_mdp5_plane_state(state)->pending = true; |
| @@ -602,6 +583,20 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane) · 371 unmodified lines | ||
| 602 | 583 | return mdp5_plane->flush_mask; |
| 603 | 584 | } |
| 604 | 585 | |
| 586 | +/* called after vsync in thread context */ | |
| 587 | +void mdp5_plane_complete_commit(struct drm_plane *plane, | |
| 588 | + struct drm_plane_state *state) | |
| 589 | +{ | |
| 590 | + struct mdp5_kms *mdp5_kms = get_kms(plane); | |
| 591 | + struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); | |
| 592 | + enum mdp5_pipe pipe = mdp5_plane->pipe; | |
| 593 | + | |
| 594 | + if (!plane_enabled(plane->state)) { | |
| 595 | + DBG("%s: free SMP", mdp5_plane->name); | |
| 596 | + mdp5_smp_release(mdp5_kms->smp, pipe); | |
| 597 | + } | |
| 598 | +} | |
| 599 | + | |
| 605 | 600 | /* initialize plane */ |
| 606 | 601 | struct drm_plane *mdp5_plane_init(struct drm_device *dev, |
| 607 | 602 | enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset) |
| @@ -34,22 +34,44 @@ · 33 unmodified lines | ||
| 34 | 34 | * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0). |
| 35 | 35 | * |
| 36 | 36 | * For each block that can be dynamically allocated, it can be either |
| 37 | − * free, or pending/in-use by a client. The updates happen in three steps: | |
| 37 | + * free: | |
| 38 | + * The block is free. | |
| 39 | + * | |
| 40 | + * pending: | |
| 41 | + * The block is allocated to some client and not free. | |
| 42 | + * | |
| 43 | + * configured: | |
| 44 | + * The block is allocated to some client, and assigned to that | |
| 45 | + * client in MDP5_MDP_SMP_ALLOC registers. | |
| 46 | + * | |
| 47 | + * inuse: | |
| 48 | + * The block is being actively used by a client. | |
| 49 | + * | |
| 50 | + * The updates happen in the following steps: | |
| 38 | 51 | * |
| 39 | 52 | * 1) mdp5_smp_request(): |
| 40 | 53 | * When plane scanout is setup, calculate required number of |
| 41 | − * blocks needed per client, and request. Blocks not inuse or | |
| 42 | − * pending by any other client are added to client's pending | |
| 43 | − * set. | |
| 54 | + * blocks needed per client, and request. Blocks neither inuse nor | |
| 55 | + * configured nor pending by any other client are added to client's | |
| 56 | + * pending set. | |
| 57 | + * For shrinking, blocks in pending but not in configured can be freed | |
| 58 | + * directly, but those already in configured will be freed later by | |
| 59 | + * mdp5_smp_commit. | |
| 44 | 60 | * |
| 45 | 61 | * 2) mdp5_smp_configure(): |
| 46 | 62 | * As hw is programmed, before FLUSH, MDP5_MDP_SMP_ALLOC registers |
| 47 | 63 | * are configured for the union(pending, inuse) |
| 64 | + * Current pending is copied to configured. | |
| 65 | + * It is assumed that mdp5_smp_request and mdp5_smp_configure not run | |
| 66 | + * concurrently for the same pipe. | |
| 48 | 67 | * |
| 49 | 68 | * 3) mdp5_smp_commit(): |
| 50 | − * After next vblank, copy pending -> inuse. Optionally update | |
| 69 | + * After next vblank, copy configured -> inuse. Optionally update | |
| 51 | 70 | * MDP5_SMP_ALLOC registers if there are newly unused blocks |
| 52 | 71 | * |
| 72 | + * 4) mdp5_smp_release(): | |
| 73 | + * Must be called after the pipe is disabled and no longer uses any SMB | |
| 74 | + * | |
| 53 | 75 | * On the next vblank after changes have been committed to hw, the |
| 54 | 76 | * client's pending blocks become it's in-use blocks (and no-longer |
| 55 | 77 | * in-use blocks become available to other clients). |
| @@ -77,6 +99,9 @@ struct mdp5_smp { · 21 unmodified lines | ||
| 77 | 99 | struct mdp5_client_smp_state client_state[MAX_CLIENTS]; |
| 78 | 100 | }; |
| 79 | 101 | |
| 102 | +static void update_smp_state(struct mdp5_smp *smp, | |
| 103 | + u32 cid, mdp5_smp_state_t *assigned); | |
| 104 | + | |
| 80 | 105 | static inline |
| 81 | 106 | struct mdp5_kms *get_kms(struct mdp5_smp *smp) |
| 82 | 107 | { |
| @@ -149,7 +174,12 @@ static int smp_request_block(struct mdp5_smp *smp, · 66 unmodified lines | ||
| 149 | 174 | for (i = cur_nblks; i > nblks; i--) { |
| 150 | 175 | int blk = find_first_bit(ps->pending, cnt); |
| 151 | 176 | clear_bit(blk, ps->pending); |
| 152 | − /* don't clear in global smp_state until _commit() */ | |
| 177 | + | |
| 178 | + /* clear in global smp_state if not in configured | |
| 179 | + * otherwise until _commit() | |
| 180 | + */ | |
| 181 | + if (!test_bit(blk, ps->configured)) | |
| 182 | + clear_bit(blk, smp->state); | |
| 153 | 183 | } |
| 154 | 184 | } |
| 155 | 185 | |
| @@ -223,10 +253,33 @@ int mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe, u32 fmt, u32 wid · 67 unmodified lines | ||
| 223 | 253 | /* Release SMP blocks for all clients of the pipe */ |
| 224 | 254 | void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe) |
| 225 | 255 | { |
| 226 | − int i, nblks; | |
| 256 | + int i; | |
| 257 | + unsigned long flags; | |
| 258 | + int cnt = smp->blk_cnt; | |
| 259 | + | |
| 260 | + for (i = 0; i < pipe2nclients(pipe); i++) { | |
| 261 | + mdp5_smp_state_t assigned; | |
| 262 | + u32 cid = pipe2client(pipe, i); | |
| 263 | + struct mdp5_client_smp_state *ps = &smp->client_state[cid]; | |
| 264 | + | |
| 265 | + spin_lock_irqsave(&smp->state_lock, flags); | |
| 266 | + | |
| 267 | + /* clear hw assignment */ | |
| 268 | + bitmap_or(assigned, ps->inuse, ps->configured, cnt); | |
| 269 | + update_smp_state(smp, CID_UNUSED, &assigned); | |
| 270 | + | |
| 271 | + /* free to global pool */ | |
| 272 | + bitmap_andnot(smp->state, smp->state, ps->pending, cnt); | |
| 273 | + bitmap_andnot(smp->state, smp->state, assigned, cnt); | |
| 274 | + | |
| 275 | + /* clear client's infor */ | |
| 276 | + bitmap_zero(ps->pending, cnt); | |
| 277 | + bitmap_zero(ps->configured, cnt); | |
| 278 | + bitmap_zero(ps->inuse, cnt); | |
| 279 | + | |
| 280 | + spin_unlock_irqrestore(&smp->state_lock, flags); | |
| 281 | + } | |
| 227 | 282 | |
| 228 | − for (i = 0, nblks = 0; i < pipe2nclients(pipe); i++) | |
| 229 | − smp_request_block(smp, pipe2client(pipe, i), 0); | |
| 230 | 283 | set_fifo_thresholds(smp, pipe, 0); |
| 231 | 284 | } |
| 232 | 285 | |
| @@ -274,12 +327,20 @@ void mdp5_smp_configure(struct mdp5_smp *smp, enum mdp5_pipe pipe) · 41 unmodified lines | ||
| 274 | 327 | u32 cid = pipe2client(pipe, i); |
| 275 | 328 | struct mdp5_client_smp_state *ps = &smp->client_state[cid]; |
| 276 | 329 | |
| 277 | − bitmap_or(assigned, ps->inuse, ps->pending, cnt); | |
| 330 | + /* | |
| 331 | + * if vblank has not happened since last smp_configure | |
| 332 | + * skip the configure for now | |
| 333 | + */ | |
| 334 | + if (!bitmap_equal(ps->inuse, ps->configured, cnt)) | |
| 335 | + continue; | |
| 336 | + | |
| 337 | + bitmap_copy(ps->configured, ps->pending, cnt); | |
| 338 | + bitmap_or(assigned, ps->inuse, ps->configured, cnt); | |
| 278 | 339 | update_smp_state(smp, cid, &assigned); |
| 279 | 340 | } |
| 280 | 341 | } |
| 281 | 342 | |
| 282 | −/* step #3: after vblank, copy pending -> inuse: */ | |
| 343 | +/* step #3: after vblank, copy configured -> inuse: */ | |
| 283 | 344 | void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) |
| 284 | 345 | { |
| 285 | 346 | int cnt = smp->blk_cnt; |
| @@ -295,7 +356,7 @@ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) · 9 unmodified lines | ||
| 295 | 356 | * using, which can be released and made available to other |
| 296 | 357 | * clients: |
| 297 | 358 | */ |
| 298 | − if (bitmap_andnot(released, ps->inuse, ps->pending, cnt)) { | |
| 359 | + if (bitmap_andnot(released, ps->inuse, ps->configured, cnt)) { | |
| 299 | 360 | unsigned long flags; |
| 300 | 361 | |
| 301 | 362 | spin_lock_irqsave(&smp->state_lock, flags); |
| @@ -306,7 +367,7 @@ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) · 4 unmodified lines | ||
| 306 | 367 | update_smp_state(smp, CID_UNUSED, &released); |
| 307 | 368 | } |
| 308 | 369 | |
| 309 | − bitmap_copy(ps->inuse, ps->pending, cnt); | |
| 370 | + bitmap_copy(ps->inuse, ps->configured, cnt); | |
| 310 | 371 | } |
| 311 | 372 | } |
| 312 | 373 | |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | struct mdp5_client_smp_state { |
| 25 | 25 | mdp5_smp_state_t inuse; |
| 26 | + mdp5_smp_state_t configured; | |
| 26 | 27 | mdp5_smp_state_t pending; |
| 27 | 28 | }; |
| 28 | 29 | |
| @@ -283,12 +283,8 @@ int msm_atomic_commit(struct drm_device *dev, · 282 unmodified lines | ||
| 283 | 283 | |
| 284 | 284 | timeout = ktime_add_ms(ktime_get(), 1000); |
| 285 | 285 | |
| 286 | − ret = msm_wait_fence_interruptable(dev, c->fence, &timeout); | |
| 287 | − if (ret) { | |
| 288 | − WARN_ON(ret); // TODO unswap state back? or?? | |
| 289 | − commit_destroy(c); | |
| 290 | − return ret; | |
| 291 | − } | |
| 286 | + /* uninterruptible wait */ | |
| 287 | + msm_wait_fence(dev, c->fence, &timeout, false); | |
| 292 | 288 | |
| 293 | 289 | complete_commit(c); |
| 294 | 290 | |
| @@ -637,8 +637,8 @@ static void msm_debugfs_cleanup(struct drm_minor *minor) · 636 unmodified lines | ||
| 637 | 637 | * Fences: |
| 638 | 638 | */ |
| 639 | 639 | |
| 640 | −int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, | |
| 641 | − ktime_t *timeout) | |
| 640 | +int msm_wait_fence(struct drm_device *dev, uint32_t fence, | |
| 641 | + ktime_t *timeout , bool interruptible) | |
| 642 | 642 | { |
| 643 | 643 | struct msm_drm_private *priv = dev->dev_private; |
| 644 | 644 | int ret; |
| @@ -667,7 +667,12 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, · 22 unmodified lines | ||
| 667 | 667 | remaining_jiffies = timespec_to_jiffies(&ts); |
| 668 | 668 | } |
| 669 | 669 | |
| 670 | − ret = wait_event_interruptible_timeout(priv->fence_event, | |
| 670 | + if (interruptible) | |
| 671 | + ret = wait_event_interruptible_timeout(priv->fence_event, | |
| 672 | + fence_completed(dev, fence), | |
| 673 | + remaining_jiffies); | |
| 674 | + else | |
| 675 | + ret = wait_event_timeout(priv->fence_event, | |
| 671 | 676 | fence_completed(dev, fence), |
| 672 | 677 | remaining_jiffies); |
| 673 | 678 | |
| @@ -853,7 +858,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, · 179 unmodified lines | ||
| 853 | 858 | return -EINVAL; |
| 854 | 859 | } |
| 855 | 860 | |
| 856 | − return msm_wait_fence_interruptable(dev, args->fence, &timeout); | |
| 861 | + return msm_wait_fence(dev, args->fence, &timeout, true); | |
| 857 | 862 | } |
| 858 | 863 | |
| 859 | 864 | static const struct drm_ioctl_desc msm_ioctls[] = { |
| @@ -164,8 +164,8 @@ int msm_atomic_commit(struct drm_device *dev, · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); |
| 166 | 166 | |
| 167 | −int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, | |
| 168 | − ktime_t *timeout); | |
| 167 | +int msm_wait_fence(struct drm_device *dev, uint32_t fence, | |
| 168 | + ktime_t *timeout, bool interruptible); | |
| 169 | 169 | int msm_queue_fence_cb(struct drm_device *dev, |
| 170 | 170 | struct msm_fence_cb *cb, uint32_t fence); |
| 171 | 171 | void msm_update_fence(struct drm_device *dev, uint32_t fence); |
| @@ -460,7 +460,7 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) · 459 unmodified lines | ||
| 460 | 460 | if (op & MSM_PREP_NOSYNC) |
| 461 | 461 | timeout = NULL; |
| 462 | 462 | |
| 463 | − ret = msm_wait_fence_interruptable(dev, fence, timeout); | |
| 463 | + ret = msm_wait_fence(dev, fence, timeout, true); | |
| 464 | 464 | } |
| 465 | 465 | |
| 466 | 466 | /* TODO cache maintenance */ |
| @@ -23,8 +23,12 @@ · 22 unmodified lines | ||
| 23 | 23 | struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) |
| 24 | 24 | { |
| 25 | 25 | struct msm_gem_object *msm_obj = to_msm_bo(obj); |
| 26 | − BUG_ON(!msm_obj->sgt); /* should have already pinned! */ | |
| 27 | − return msm_obj->sgt; | |
| 26 | + int npages = obj->size >> PAGE_SHIFT; | |
| 27 | + | |
| 28 | + if (WARN_ON(!msm_obj->pages)) /* should have already pinned! */ | |
| 29 | + return NULL; | |
| 30 | + | |
| 31 | + return drm_prime_pages_to_sg(msm_obj->pages, npages); | |
| 28 | 32 | } |
| 29 | 33 | |
| 30 | 34 | void *msm_gem_prime_vmap(struct drm_gem_object *obj) |
| @@ -128,6 +128,7 @@ nouveau_cli_destroy(struct nouveau_cli *cli) · 127 unmodified lines | ||
| 128 | 128 | nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL); |
| 129 | 129 | nvif_client_fini(&cli->base); |
| 130 | 130 | usif_client_fini(cli); |
| 131 | + kfree(cli); | |
| 131 | 132 | } |
| 132 | 133 | |
| 133 | 134 | static void |
| @@ -865,8 +866,10 @@ nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv) · 731 unmodified lines | ||
| 865 | 866 | |
| 866 | 867 | pm_runtime_get_sync(dev->dev); |
| 867 | 868 | |
| 869 | + mutex_lock(&cli->mutex); | |
| 868 | 870 | if (cli->abi16) |
| 869 | 871 | nouveau_abi16_fini(cli->abi16); |
| 872 | + mutex_unlock(&cli->mutex); | |
| 870 | 873 | |
| 871 | 874 | mutex_lock(&drm->client.mutex); |
| 872 | 875 | list_del(&cli->head); |
| @@ -92,6 +92,8 @@ static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu) · 91 unmodified lines | ||
| 92 | 92 | return 0; |
| 93 | 93 | } |
| 94 | 94 | |
| 95 | +#if IS_ENABLED(CONFIG_IOMMU_API) | |
| 96 | + | |
| 95 | 97 | static void nouveau_platform_probe_iommu(struct device *dev, |
| 96 | 98 | struct nouveau_platform_gpu *gpu) |
| 97 | 99 | { |
| @@ -158,6 +160,20 @@ static void nouveau_platform_remove_iommu(struct device *dev, · 60 unmodified lines | ||
| 158 | 160 | } |
| 159 | 161 | } |
| 160 | 162 | |
| 163 | +#else | |
| 164 | + | |
| 165 | +static void nouveau_platform_probe_iommu(struct device *dev, | |
| 166 | + struct nouveau_platform_gpu *gpu) | |
| 167 | +{ | |
| 168 | +} | |
| 169 | + | |
| 170 | +static void nouveau_platform_remove_iommu(struct device *dev, | |
| 171 | + struct nouveau_platform_gpu *gpu) | |
| 172 | +{ | |
| 173 | +} | |
| 174 | + | |
| 175 | +#endif | |
| 176 | + | |
| 161 | 177 | static int nouveau_platform_probe(struct platform_device *pdev) |
| 162 | 178 | { |
| 163 | 179 | struct nouveau_platform_gpu *gpu; |
| @@ -175,15 +175,24 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, · 174 unmodified lines | ||
| 175 | 175 | node->page_shift = 12; |
| 176 | 176 | |
| 177 | 177 | switch (drm->device.info.family) { |
| 178 | + case NV_DEVICE_INFO_V0_TNT: | |
| 179 | + case NV_DEVICE_INFO_V0_CELSIUS: | |
| 180 | + case NV_DEVICE_INFO_V0_KELVIN: | |
| 181 | + case NV_DEVICE_INFO_V0_RANKINE: | |
| 182 | + case NV_DEVICE_INFO_V0_CURIE: | |
| 183 | + break; | |
| 178 | 184 | case NV_DEVICE_INFO_V0_TESLA: |
| 179 | 185 | if (drm->device.info.chipset != 0x50) |
| 180 | 186 | node->memtype = (nvbo->tile_flags & 0x7f00) >> 8; |
| 181 | 187 | break; |
| 182 | 188 | case NV_DEVICE_INFO_V0_FERMI: |
| 183 | 189 | case NV_DEVICE_INFO_V0_KEPLER: |
| 190 | + case NV_DEVICE_INFO_V0_MAXWELL: | |
| 184 | 191 | node->memtype = (nvbo->tile_flags & 0xff00) >> 8; |
| 185 | 192 | break; |
| 186 | 193 | default: |
| 194 | + NV_WARN(drm, "%s: unhandled family type %x\n", __func__, | |
| 195 | + drm->device.info.family); | |
| 187 | 196 | break; |
| 188 | 197 | } |
| 189 | 198 | |
| @@ -203,7 +203,7 @@ nv04_fbcon_accel_init(struct fb_info *info) · 202 unmodified lines | ||
| 203 | 203 | if (ret) |
| 204 | 204 | return ret; |
| 205 | 205 | |
| 206 | − if (RING_SPACE(chan, 49)) { | |
| 206 | + if (RING_SPACE(chan, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) { | |
| 207 | 207 | nouveau_fbcon_gpu_lockup(info); |
| 208 | 208 | return 0; |
| 209 | 209 | } |
| @@ -979,7 +979,7 @@ nv50_crtc_cursor_show_hide(struct nouveau_crtc *nv_crtc, bool show, bool update) · 978 unmodified lines | ||
| 979 | 979 | { |
| 980 | 980 | struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); |
| 981 | 981 | |
| 982 | − if (show && nv_crtc->cursor.nvbo) | |
| 982 | + if (show && nv_crtc->cursor.nvbo && nv_crtc->base.enabled) | |
| 983 | 983 | nv50_crtc_cursor_show(nv_crtc); |
| 984 | 984 | else |
| 985 | 985 | nv50_crtc_cursor_hide(nv_crtc); |
| @@ -188,7 +188,7 @@ nv50_fbcon_accel_init(struct fb_info *info) · 187 unmodified lines | ||
| 188 | 188 | if (ret) |
| 189 | 189 | return ret; |
| 190 | 190 | |
| 191 | − ret = RING_SPACE(chan, 59); | |
| 191 | + ret = RING_SPACE(chan, 58); | |
| 192 | 192 | if (ret) { |
| 193 | 193 | nouveau_fbcon_gpu_lockup(info); |
| 194 | 194 | return ret; |
| @@ -252,6 +252,7 @@ nv50_fbcon_accel_init(struct fb_info *info) · 57 unmodified lines | ||
| 252 | 252 | OUT_RING(chan, info->var.yres_virtual); |
| 253 | 253 | OUT_RING(chan, upper_32_bits(fb->vma.offset)); |
| 254 | 254 | OUT_RING(chan, lower_32_bits(fb->vma.offset)); |
| 255 | + FIRE_RING(chan); | |
| 255 | 256 | |
| 256 | 257 | return 0; |
| 257 | 258 | } |
| @@ -188,7 +188,7 @@ nvc0_fbcon_accel_init(struct fb_info *info) · 187 unmodified lines | ||
| 188 | 188 | return -EINVAL; |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | − ret = RING_SPACE(chan, 60); | |
| 191 | + ret = RING_SPACE(chan, 58); | |
| 192 | 192 | if (ret) { |
| 193 | 193 | WARN_ON(1); |
| 194 | 194 | nouveau_fbcon_gpu_lockup(info); |
| @@ -809,7 +809,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, · 808 unmodified lines | ||
| 809 | 809 | case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; |
| 810 | 810 | default: |
| 811 | 811 | nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); |
| 812 | − return 0x0000; | |
| 812 | + return NULL; | |
| 813 | 813 | } |
| 814 | 814 | } |
| 815 | 815 | |
| @@ -165,15 +165,31 @@ gk104_fifo_context_attach(struct nvkm_object *parent, · 164 unmodified lines | ||
| 165 | 165 | return 0; |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | +static int | |
| 169 | +gk104_fifo_chan_kick(struct gk104_fifo_chan *chan) | |
| 170 | +{ | |
| 171 | + struct nvkm_object *obj = (void *)chan; | |
| 172 | + struct gk104_fifo_priv *priv = (void *)obj->engine; | |
| 173 | + | |
| 174 | + nv_wr32(priv, 0x002634, chan->base.chid); | |
| 175 | + if (!nv_wait(priv, 0x002634, 0x100000, 0x000000)) { | |
| 176 | + nv_error(priv, "channel %d [%s] kick timeout\n", | |
| 177 | + chan->base.chid, nvkm_client_name(chan)); | |
| 178 | + return -EBUSY; | |
| 179 | + } | |
| 180 | + | |
| 181 | + return 0; | |
| 182 | +} | |
| 183 | + | |
| 168 | 184 | static int |
| 169 | 185 | gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, |
| 170 | 186 | struct nvkm_object *object) |
| 171 | 187 | { |
| 172 | 188 | struct nvkm_bar *bar = nvkm_bar(parent); |
| 173 | − struct gk104_fifo_priv *priv = (void *)parent->engine; | |
| 174 | 189 | struct gk104_fifo_base *base = (void *)parent->parent; |
| 175 | 190 | struct gk104_fifo_chan *chan = (void *)parent; |
| 176 | 191 | u32 addr; |
| 192 | + int ret; | |
| 177 | 193 | |
| 178 | 194 | switch (nv_engidx(object->engine)) { |
| 179 | 195 | case NVDEV_ENGINE_SW : return 0; |
| @@ -188,13 +204,9 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, · 8 unmodified lines | ||
| 188 | 204 | return -EINVAL; |
| 189 | 205 | } |
| 190 | 206 | |
| 191 | − nv_wr32(priv, 0x002634, chan->base.chid); | |
| 192 | − if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { | |
| 193 | − nv_error(priv, "channel %d [%s] kick timeout\n", | |
| 194 | − chan->base.chid, nvkm_client_name(chan)); | |
| 195 | − if (suspend) | |
| 196 | − return -EBUSY; | |
| 197 | − } | |
| 207 | + ret = gk104_fifo_chan_kick(chan); | |
| 208 | + if (ret && suspend) | |
| 209 | + return ret; | |
| 198 | 210 | |
| 199 | 211 | if (addr) { |
| 200 | 212 | nv_wo32(base, addr + 0x00, 0x00000000); |
| @@ -319,6 +331,7 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend) · 118 unmodified lines | ||
| 319 | 331 | gk104_fifo_runlist_update(priv, chan->engine); |
| 320 | 332 | } |
| 321 | 333 | |
| 334 | + gk104_fifo_chan_kick(chan); | |
| 322 | 335 | nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); |
| 323 | 336 | return nvkm_fifo_channel_fini(&chan->base, suspend); |
| 324 | 337 | } |
| @@ -663,6 +663,37 @@ gf100_gr_zbc_init(struct gf100_gr_priv *priv) · 662 unmodified lines | ||
| 663 | 663 | gf100_gr_zbc_clear_depth(priv, index); |
| 664 | 664 | } |
| 665 | 665 | |
| 666 | +/** | |
| 667 | + * Wait until GR goes idle. GR is considered idle if it is disabled by the | |
| 668 | + * MC (0x200) register, or GR is not busy and a context switch is not in | |
| 669 | + * progress. | |
| 670 | + */ | |
| 671 | +int | |
| 672 | +gf100_gr_wait_idle(struct gf100_gr_priv *priv) | |
| 673 | +{ | |
| 674 | + unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000); | |
| 675 | + bool gr_enabled, ctxsw_active, gr_busy; | |
| 676 | + | |
| 677 | + do { | |
| 678 | + /* | |
| 679 | + * required to make sure FIFO_ENGINE_STATUS (0x2640) is | |
| 680 | + * up-to-date | |
| 681 | + */ | |
| 682 | + nv_rd32(priv, 0x400700); | |
| 683 | + | |
| 684 | + gr_enabled = nv_rd32(priv, 0x200) & 0x1000; | |
| 685 | + ctxsw_active = nv_rd32(priv, 0x2640) & 0x8000; | |
| 686 | + gr_busy = nv_rd32(priv, 0x40060c) & 0x1; | |
| 687 | + | |
| 688 | + if (!gr_enabled || (!gr_busy && !ctxsw_active)) | |
| 689 | + return 0; | |
| 690 | + } while (time_before(jiffies, end_jiffies)); | |
| 691 | + | |
| 692 | + nv_error(priv, "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n", | |
| 693 | + gr_enabled, ctxsw_active, gr_busy); | |
| 694 | + return -EAGAIN; | |
| 695 | +} | |
| 696 | + | |
| 666 | 697 | void |
| 667 | 698 | gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) |
| 668 | 699 | { |
| @@ -699,7 +730,13 @@ gf100_gr_icmd(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) · 30 unmodified lines | ||
| 699 | 730 | |
| 700 | 731 | while (addr < next) { |
| 701 | 732 | nv_wr32(priv, 0x400200, addr); |
| 702 | − nv_wait(priv, 0x400700, 0x00000002, 0x00000000); | |
| 733 | + /** | |
| 734 | + * Wait for GR to go idle after submitting a | |
| 735 | + * GO_IDLE bundle | |
| 736 | + */ | |
| 737 | + if ((addr & 0xffff) == 0xe100) | |
| 738 | + gf100_gr_wait_idle(priv); | |
| 739 | + nv_wait(priv, 0x400700, 0x00000004, 0x00000000); | |
| 703 | 740 | addr += init->pitch; |
| 704 | 741 | } |
| 705 | 742 | } |
| @@ -181,6 +181,7 @@ struct gf100_gr_oclass { · 180 unmodified lines | ||
| 181 | 181 | int ppc_nr; |
| 182 | 182 | }; |
| 183 | 183 | |
| 184 | +int gf100_gr_wait_idle(struct gf100_gr_priv *); | |
| 184 | 185 | void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *); |
| 185 | 186 | void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *); |
| 186 | 187 | void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *); |
| @@ -332,9 +332,12 @@ static void · 331 unmodified lines | ||
| 332 | 332 | nvkm_perfctx_dtor(struct nvkm_object *object) |
| 333 | 333 | { |
| 334 | 334 | struct nvkm_pm *ppm = (void *)object->engine; |
| 335 | + struct nvkm_perfctx *ctx = (void *)object; | |
| 336 | + | |
| 335 | 337 | mutex_lock(&nv_subdev(ppm)->mutex); |
| 336 | − nvkm_engctx_destroy(&ppm->context->base); | |
| 337 | − ppm->context = NULL; | |
| 338 | + nvkm_engctx_destroy(&ctx->base); | |
| 339 | + if (ppm->context == ctx) | |
| 340 | + ppm->context = NULL; | |
| 338 | 341 | mutex_unlock(&nv_subdev(ppm)->mutex); |
| 339 | 342 | } |
| 340 | 343 | |
| @@ -355,12 +358,11 @@ nvkm_perfctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine, · 14 unmodified lines | ||
| 355 | 358 | mutex_lock(&nv_subdev(ppm)->mutex); |
| 356 | 359 | if (ppm->context == NULL) |
| 357 | 360 | ppm->context = ctx; |
| 358 | − mutex_unlock(&nv_subdev(ppm)->mutex); | |
| 359 | − | |
| 360 | 361 | if (ctx != ppm->context) |
| 361 | − return -EBUSY; | |
| 362 | + ret = -EBUSY; | |
| 363 | + mutex_unlock(&nv_subdev(ppm)->mutex); | |
| 362 | 364 | |
| 363 | − return 0; | |
| 365 | + return ret; | |
| 364 | 366 | } |
| 365 | 367 | |
| 366 | 368 | struct nvkm_oclass |
| @@ -1284,6 +1284,44 @@ init_zm_reg_sequence(struct nvbios_init *init) · 1283 unmodified lines | ||
| 1284 | 1284 | } |
| 1285 | 1285 | } |
| 1286 | 1286 | |
| 1287 | +/** | |
| 1288 | + * INIT_PLL_INDIRECT - opcode 0x59 | |
| 1289 | + * | |
| 1290 | + */ | |
| 1291 | +static void | |
| 1292 | +init_pll_indirect(struct nvbios_init *init) | |
| 1293 | +{ | |
| 1294 | + struct nvkm_bios *bios = init->bios; | |
| 1295 | + u32 reg = nv_ro32(bios, init->offset + 1); | |
| 1296 | + u16 addr = nv_ro16(bios, init->offset + 5); | |
| 1297 | + u32 freq = (u32)nv_ro16(bios, addr) * 1000; | |
| 1298 | + | |
| 1299 | + trace("PLL_INDIRECT\tR[0x%06x] =PLL= VBIOS[%04x] = %dkHz\n", | |
| 1300 | + reg, addr, freq); | |
| 1301 | + init->offset += 7; | |
| 1302 | + | |
| 1303 | + init_prog_pll(init, reg, freq); | |
| 1304 | +} | |
| 1305 | + | |
| 1306 | +/** | |
| 1307 | + * INIT_ZM_REG_INDIRECT - opcode 0x5a | |
| 1308 | + * | |
| 1309 | + */ | |
| 1310 | +static void | |
| 1311 | +init_zm_reg_indirect(struct nvbios_init *init) | |
| 1312 | +{ | |
| 1313 | + struct nvkm_bios *bios = init->bios; | |
| 1314 | + u32 reg = nv_ro32(bios, init->offset + 1); | |
| 1315 | + u16 addr = nv_ro16(bios, init->offset + 5); | |
| 1316 | + u32 data = nv_ro32(bios, addr); | |
| 1317 | + | |
| 1318 | + trace("ZM_REG_INDIRECT\tR[0x%06x] = VBIOS[0x%04x] = 0x%08x\n", | |
| 1319 | + reg, addr, data); | |
| 1320 | + init->offset += 7; | |
| 1321 | + | |
| 1322 | + init_wr32(init, addr, data); | |
| 1323 | +} | |
| 1324 | + | |
| 1287 | 1325 | /** |
| 1288 | 1326 | * INIT_SUB_DIRECT - opcode 0x5b |
| 1289 | 1327 | * |
| @@ -2145,6 +2183,8 @@ static struct nvbios_init_opcode { · 855 unmodified lines | ||
| 2145 | 2183 | [0x56] = { init_condition_time }, |
| 2146 | 2184 | [0x57] = { init_ltime }, |
| 2147 | 2185 | [0x58] = { init_zm_reg_sequence }, |
| 2186 | + [0x59] = { init_pll_indirect }, | |
| 2187 | + [0x5a] = { init_zm_reg_indirect }, | |
| 2148 | 2188 | [0x5b] = { init_sub_direct }, |
| 2149 | 2189 | [0x5c] = { init_jump }, |
| 2150 | 2190 | [0x5e] = { init_i2c_if }, |
| @@ -180,7 +180,8 @@ gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz, · 179 unmodified lines | ||
| 180 | 180 | struct gt215_clk_info *info) |
| 181 | 181 | { |
| 182 | 182 | struct gt215_clk_priv *priv = (void *)clock; |
| 183 | − u32 oclk, sclk, sdiv, diff; | |
| 183 | + u32 oclk, sclk, sdiv; | |
| 184 | + s32 diff; | |
| 184 | 185 | |
| 185 | 186 | info->clk = 0; |
| 186 | 187 | |
| @@ -38,6 +38,14 @@ gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv) · 37 unmodified lines | ||
| 38 | 38 | nv_wr32(priv, 0x12004c, 0x4); |
| 39 | 39 | nv_wr32(priv, 0x122204, 0x2); |
| 40 | 40 | nv_rd32(priv, 0x122204); |
| 41 | + | |
| 42 | + /* | |
| 43 | + * Bug: increase clock timeout to avoid operation failure at high | |
| 44 | + * gpcclk rate. | |
| 45 | + */ | |
| 46 | + nv_wr32(priv, 0x122354, 0x800); | |
| 47 | + nv_wr32(priv, 0x128328, 0x800); | |
| 48 | + nv_wr32(priv, 0x124320, 0x800); | |
| 41 | 49 | } |
| 42 | 50 | |
| 43 | 51 | static void |
| @@ -50,7 +50,12 @@ nv04_instobj_dtor(struct nvkm_object *object) · 49 unmodified lines | ||
| 50 | 50 | { |
| 51 | 51 | struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object); |
| 52 | 52 | struct nv04_instobj_priv *node = (void *)object; |
| 53 | + struct nvkm_subdev *subdev = (void *)priv; | |
| 54 | + | |
| 55 | + mutex_lock(&subdev->mutex); | |
| 53 | 56 | nvkm_mm_free(&priv->heap, &node->mem); |
| 57 | + mutex_unlock(&subdev->mutex); | |
| 58 | + | |
| 54 | 59 | nvkm_instobj_destroy(&node->base); |
| 55 | 60 | } |
| 56 | 61 | |
| @@ -62,6 +67,7 @@ nv04_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, · 5 unmodified lines | ||
| 62 | 67 | struct nv04_instmem_priv *priv = (void *)nvkm_instmem(parent); |
| 63 | 68 | struct nv04_instobj_priv *node; |
| 64 | 69 | struct nvkm_instobj_args *args = data; |
| 70 | + struct nvkm_subdev *subdev = (void *)priv; | |
| 65 | 71 | int ret; |
| 66 | 72 | |
| 67 | 73 | if (!args->align) |
| @@ -72,8 +78,10 @@ nv04_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, · 4 unmodified lines | ||
| 72 | 78 | if (ret) |
| 73 | 79 | return ret; |
| 74 | 80 | |
| 81 | + mutex_lock(&subdev->mutex); | |
| 75 | 82 | ret = nvkm_mm_head(&priv->heap, 0, 1, args->size, args->size, |
| 76 | 83 | args->align, &node->mem); |
| 84 | + mutex_unlock(&subdev->mutex); | |
| 77 | 85 | if (ret) |
| 78 | 86 | return ret; |
| 79 | 87 | |
| @@ -2299,8 +2299,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, · 2298 unmodified lines | ||
| 2299 | 2299 | encoder_mode = atombios_get_encoder_mode(encoder); |
| 2300 | 2300 | if (connector && (radeon_audio != 0) && |
| 2301 | 2301 | ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || |
| 2302 | − (ENCODER_MODE_IS_DP(encoder_mode) && | |
| 2303 | − drm_detect_monitor_audio(radeon_connector_edid(connector))))) | |
| 2302 | + ENCODER_MODE_IS_DP(encoder_mode))) | |
| 2304 | 2303 | radeon_audio_mode_set(encoder, adjusted_mode); |
| 2305 | 2304 | } |
| 2306 | 2305 | |
| @@ -93,30 +93,26 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder) · 92 unmodified lines | ||
| 93 | 93 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 94 | 94 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 95 | 95 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 96 | − u32 offset; | |
| 97 | 96 | |
| 98 | − if (!dig || !dig->afmt || !dig->afmt->pin) | |
| 97 | + if (!dig || !dig->afmt || !dig->pin) | |
| 99 | 98 | return; |
| 100 | 99 | |
| 101 | − offset = dig->afmt->offset; | |
| 102 | − | |
| 103 | − WREG32(AFMT_AUDIO_SRC_CONTROL + offset, | |
| 104 | − AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id)); | |
| 100 | + WREG32(AFMT_AUDIO_SRC_CONTROL + dig->afmt->offset, | |
| 101 | + AFMT_AUDIO_SRC_SELECT(dig->pin->id)); | |
| 105 | 102 | } |
| 106 | 103 | |
| 107 | 104 | void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, |
| 108 | − struct drm_connector *connector, struct drm_display_mode *mode) | |
| 105 | + struct drm_connector *connector, | |
| 106 | + struct drm_display_mode *mode) | |
| 109 | 107 | { |
| 110 | 108 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 111 | 109 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 112 | 110 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 113 | − u32 tmp = 0, offset; | |
| 111 | + u32 tmp = 0; | |
| 114 | 112 | |
| 115 | − if (!dig || !dig->afmt || !dig->afmt->pin) | |
| 113 | + if (!dig || !dig->afmt || !dig->pin) | |
| 116 | 114 | return; |
| 117 | 115 | |
| 118 | − offset = dig->afmt->pin->offset; | |
| 119 | − | |
| 120 | 116 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
| 121 | 117 | if (connector->latency_present[1]) |
| 122 | 118 | tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | |
| @@ -130,24 +126,24 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, · 7 unmodified lines | ||
| 130 | 126 | else |
| 131 | 127 | tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0); |
| 132 | 128 | } |
| 133 | − WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp); | |
| 129 | + WREG32_ENDPOINT(dig->pin->offset, | |
| 130 | + AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp); | |
| 134 | 131 | } |
| 135 | 132 | |
| 136 | 133 | void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, |
| 137 | − u8 *sadb, int sad_count) | |
| 134 | + u8 *sadb, int sad_count) | |
| 138 | 135 | { |
| 139 | 136 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 140 | 137 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 141 | 138 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 142 | − u32 offset, tmp; | |
| 139 | + u32 tmp; | |
| 143 | 140 | |
| 144 | − if (!dig || !dig->afmt || !dig->afmt->pin) | |
| 141 | + if (!dig || !dig->afmt || !dig->pin) | |
| 145 | 142 | return; |
| 146 | 143 | |
| 147 | − offset = dig->afmt->pin->offset; | |
| 148 | − | |
| 149 | 144 | /* program the speaker allocation */ |
| 150 | − tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); | |
| 145 | + tmp = RREG32_ENDPOINT(dig->pin->offset, | |
| 146 | + AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); | |
| 151 | 147 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); |
| 152 | 148 | /* set HDMI mode */ |
| 153 | 149 | tmp |= HDMI_CONNECTION; |
| @@ -155,24 +151,24 @@ void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, · 1 unmodified line | ||
| 155 | 151 | tmp |= SPEAKER_ALLOCATION(sadb[0]); |
| 156 | 152 | else |
| 157 | 153 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ |
| 158 | − WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); | |
| 154 | + WREG32_ENDPOINT(dig->pin->offset, | |
| 155 | + AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); | |
| 159 | 156 | } |
| 160 | 157 | |
| 161 | 158 | void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, |
| 162 | − u8 *sadb, int sad_count) | |
| 159 | + u8 *sadb, int sad_count) | |
| 163 | 160 | { |
| 164 | 161 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 165 | 162 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 166 | 163 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 167 | − u32 offset, tmp; | |
| 164 | + u32 tmp; | |
| 168 | 165 | |
| 169 | − if (!dig || !dig->afmt || !dig->afmt->pin) | |
| 166 | + if (!dig || !dig->afmt || !dig->pin) | |
| 170 | 167 | return; |
| 171 | 168 | |
| 172 | − offset = dig->afmt->pin->offset; | |
| 173 | − | |
| 174 | 169 | /* program the speaker allocation */ |
| 175 | − tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); | |
| 170 | + tmp = RREG32_ENDPOINT(dig->pin->offset, | |
| 171 | + AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); | |
| 176 | 172 | tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); |
| 177 | 173 | /* set DP mode */ |
| 178 | 174 | tmp |= DP_CONNECTION; |
| @@ -180,13 +176,13 @@ void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, · 1 unmodified line | ||
| 180 | 176 | tmp |= SPEAKER_ALLOCATION(sadb[0]); |
| 181 | 177 | else |
| 182 | 178 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ |
| 183 | − WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); | |
| 179 | + WREG32_ENDPOINT(dig->pin->offset, | |
| 180 | + AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); | |
| 184 | 181 | } |
| 185 | 182 | |
| 186 | 183 | void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, |
| 187 | − struct cea_sad *sads, int sad_count) | |
| 184 | + struct cea_sad *sads, int sad_count) | |
| 188 | 185 | { |
| 189 | − u32 offset; | |
| 190 | 186 | int i; |
| 191 | 187 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 192 | 188 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| @@ -206,11 +202,9 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, · 13 unmodified lines | ||
| 206 | 202 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, |
| 207 | 203 | }; |
| 208 | 204 | |
| 209 | − if (!dig || !dig->afmt || !dig->afmt->pin) | |
| 205 | + if (!dig || !dig->afmt || !dig->pin) | |
| 210 | 206 | return; |
| 211 | 207 | |
| 212 | − offset = dig->afmt->pin->offset; | |
| 213 | − | |
| 214 | 208 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { |
| 215 | 209 | u32 value = 0; |
| 216 | 210 | u8 stereo_freqs = 0; |
| @@ -237,7 +231,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, · 20 unmodified lines | ||
| 237 | 231 | |
| 238 | 232 | value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); |
| 239 | 233 | |
| 240 | − WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value); | |
| 234 | + WREG32_ENDPOINT(dig->pin->offset, eld_reg_to_type[i][0], value); | |
| 241 | 235 | } |
| 242 | 236 | } |
| 243 | 237 | |
| @@ -253,7 +247,7 @@ void dce6_audio_enable(struct radeon_device *rdev, · 9 unmodified lines | ||
| 253 | 247 | } |
| 254 | 248 | |
| 255 | 249 | void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, |
| 256 | − struct radeon_crtc *crtc, unsigned int clock) | |
| 250 | + struct radeon_crtc *crtc, unsigned int clock) | |
| 257 | 251 | { |
| 258 | 252 | /* Two dtos; generally use dto0 for HDMI */ |
| 259 | 253 | u32 value = 0; |
| @@ -272,7 +266,7 @@ void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, · 12 unmodified lines | ||
| 272 | 266 | } |
| 273 | 267 | |
| 274 | 268 | void dce6_dp_audio_set_dto(struct radeon_device *rdev, |
| 275 | − struct radeon_crtc *crtc, unsigned int clock) | |
| 269 | + struct radeon_crtc *crtc, unsigned int clock) | |
| 276 | 270 | { |
| 277 | 271 | /* Two dtos; generally use dto1 for DP */ |
| 278 | 272 | u32 value = 0; |
| @@ -245,6 +245,28 @@ static struct radeon_audio_funcs dce6_dp_funcs = { · 244 unmodified lines | ||
| 245 | 245 | static void radeon_audio_enable(struct radeon_device *rdev, |
| 246 | 246 | struct r600_audio_pin *pin, u8 enable_mask) |
| 247 | 247 | { |
| 248 | + struct drm_encoder *encoder; | |
| 249 | + struct radeon_encoder *radeon_encoder; | |
| 250 | + struct radeon_encoder_atom_dig *dig; | |
| 251 | + int pin_count = 0; | |
| 252 | + | |
| 253 | + if (!pin) | |
| 254 | + return; | |
| 255 | + | |
| 256 | + if (rdev->mode_info.mode_config_initialized) { | |
| 257 | + list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) { | |
| 258 | + if (radeon_encoder_is_digital(encoder)) { | |
| 259 | + radeon_encoder = to_radeon_encoder(encoder); | |
| 260 | + dig = radeon_encoder->enc_priv; | |
| 261 | + if (dig->pin == pin) | |
| 262 | + pin_count++; | |
| 263 | + } | |
| 264 | + } | |
| 265 | + | |
| 266 | + if ((pin_count > 1) && (enable_mask == 0)) | |
| 267 | + return; | |
| 268 | + } | |
| 269 | + | |
| 248 | 270 | if (rdev->audio.funcs->enable) |
| 249 | 271 | rdev->audio.funcs->enable(rdev, pin, enable_mask); |
| 250 | 272 | } |
| @@ -336,24 +358,13 @@ void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset, · 85 unmodified lines | ||
| 336 | 358 | |
| 337 | 359 | static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) |
| 338 | 360 | { |
| 339 | − struct radeon_encoder *radeon_encoder; | |
| 340 | − struct drm_connector *connector; | |
| 341 | − struct radeon_connector *radeon_connector = NULL; | |
| 361 | + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |
| 362 | + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | |
| 342 | 363 | struct cea_sad *sads; |
| 343 | 364 | int sad_count; |
| 344 | 365 | |
| 345 | − list_for_each_entry(connector, | |
| 346 | − &encoder->dev->mode_config.connector_list, head) { | |
| 347 | − if (connector->encoder == encoder) { | |
| 348 | − radeon_connector = to_radeon_connector(connector); | |
| 349 | − break; | |
| 350 | − } | |
| 351 | − } | |
| 352 | − | |
| 353 | − if (!radeon_connector) { | |
| 354 | − DRM_ERROR("Couldn't find encoder's connector\n"); | |
| 366 | + if (!connector) | |
| 355 | 367 | return; |
| 356 | − } | |
| 357 | 368 | |
| 358 | 369 | sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads); |
| 359 | 370 | if (sad_count <= 0) { |
| @@ -362,8 +373,6 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) · 2 unmodified lines | ||
| 362 | 373 | } |
| 363 | 374 | BUG_ON(!sads); |
| 364 | 375 | |
| 365 | − radeon_encoder = to_radeon_encoder(encoder); | |
| 366 | − | |
| 367 | 376 | if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs) |
| 368 | 377 | radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count); |
| 369 | 378 | |
| @@ -372,27 +381,16 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) · 2 unmodified lines | ||
| 372 | 381 | |
| 373 | 382 | static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) |
| 374 | 383 | { |
| 384 | + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |
| 375 | 385 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 376 | − struct drm_connector *connector; | |
| 377 | − struct radeon_connector *radeon_connector = NULL; | |
| 378 | 386 | u8 *sadb = NULL; |
| 379 | 387 | int sad_count; |
| 380 | 388 | |
| 381 | − list_for_each_entry(connector, | |
| 382 | − &encoder->dev->mode_config.connector_list, head) { | |
| 383 | − if (connector->encoder == encoder) { | |
| 384 | − radeon_connector = to_radeon_connector(connector); | |
| 385 | − break; | |
| 386 | − } | |
| 387 | − } | |
| 388 | − | |
| 389 | − if (!radeon_connector) { | |
| 390 | − DRM_ERROR("Couldn't find encoder's connector\n"); | |
| 389 | + if (!connector) | |
| 391 | 390 | return; |
| 392 | − } | |
| 393 | 391 | |
| 394 | − sad_count = drm_edid_to_speaker_allocation( | |
| 395 | − radeon_connector_edid(connector), &sadb); | |
| 392 | + sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), | |
| 393 | + &sadb); | |
| 396 | 394 | if (sad_count < 0) { |
| 397 | 395 | DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", |
| 398 | 396 | sad_count); |
| @@ -406,26 +404,13 @@ static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) · 7 unmodified lines | ||
| 406 | 404 | } |
| 407 | 405 | |
| 408 | 406 | static void radeon_audio_write_latency_fields(struct drm_encoder *encoder, |
| 409 | − struct drm_display_mode *mode) | |
| 407 | + struct drm_display_mode *mode) | |
| 410 | 408 | { |
| 411 | − struct radeon_encoder *radeon_encoder; | |
| 412 | − struct drm_connector *connector; | |
| 413 | − struct radeon_connector *radeon_connector = 0; | |
| 414 | − | |
| 415 | − list_for_each_entry(connector, | |
| 416 | − &encoder->dev->mode_config.connector_list, head) { | |
| 417 | − if (connector->encoder == encoder) { | |
| 418 | − radeon_connector = to_radeon_connector(connector); | |
| 419 | − break; | |
| 420 | − } | |
| 421 | − } | |
| 409 | + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |
| 410 | + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | |
| 422 | 411 | |
| 423 | − if (!radeon_connector) { | |
| 424 | − DRM_ERROR("Couldn't find encoder's connector\n"); | |
| 412 | + if (!connector) | |
| 425 | 413 | return; |
| 426 | − } | |
| 427 | − | |
| 428 | − radeon_encoder = to_radeon_encoder(encoder); | |
| 429 | 414 | |
| 430 | 415 | if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields) |
| 431 | 416 | radeon_encoder->audio->write_latency_fields(encoder, connector, mode); |
| @@ -451,29 +436,23 @@ static void radeon_audio_select_pin(struct drm_encoder *encoder) · 19 unmodified lines | ||
| 451 | 436 | } |
| 452 | 437 | |
| 453 | 438 | void radeon_audio_detect(struct drm_connector *connector, |
| 439 | + struct drm_encoder *encoder, | |
| 454 | 440 | enum drm_connector_status status) |
| 455 | 441 | { |
| 456 | − struct radeon_device *rdev; | |
| 457 | − struct radeon_encoder *radeon_encoder; | |
| 442 | + struct drm_device *dev = connector->dev; | |
| 443 | + struct radeon_device *rdev = dev->dev_private; | |
| 444 | + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | |
| 458 | 445 | struct radeon_encoder_atom_dig *dig; |
| 459 | 446 | |
| 460 | − if (!connector || !connector->encoder) | |
| 447 | + if (!radeon_audio_chipset_supported(rdev)) | |
| 461 | 448 | return; |
| 462 | 449 | |
| 463 | − rdev = connector->encoder->dev->dev_private; | |
| 464 | − | |
| 465 | − if (!radeon_audio_chipset_supported(rdev)) | |
| 450 | + if (!radeon_encoder_is_digital(encoder)) | |
| 466 | 451 | return; |
| 467 | 452 | |
| 468 | − radeon_encoder = to_radeon_encoder(connector->encoder); | |
| 469 | 453 | dig = radeon_encoder->enc_priv; |
| 470 | 454 | |
| 471 | 455 | if (status == connector_status_connected) { |
| 472 | − if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) { | |
| 473 | − radeon_encoder->audio = NULL; | |
| 474 | − return; | |
| 475 | − } | |
| 476 | − | |
| 477 | 456 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { |
| 478 | 457 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 479 | 458 | |
| @@ -486,11 +465,17 @@ void radeon_audio_detect(struct drm_connector *connector, · 6 unmodified lines | ||
| 486 | 465 | radeon_encoder->audio = rdev->audio.hdmi_funcs; |
| 487 | 466 | } |
| 488 | 467 | |
| 489 | − dig->afmt->pin = radeon_audio_get_pin(connector->encoder); | |
| 490 | − radeon_audio_enable(rdev, dig->afmt->pin, 0xf); | |
| 468 | + if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { | |
| 469 | + if (!dig->pin) | |
| 470 | + dig->pin = radeon_audio_get_pin(encoder); | |
| 471 | + radeon_audio_enable(rdev, dig->pin, 0xf); | |
| 472 | + } else { | |
| 473 | + radeon_audio_enable(rdev, dig->pin, 0); | |
| 474 | + dig->pin = NULL; | |
| 475 | + } | |
| 491 | 476 | } else { |
| 492 | − radeon_audio_enable(rdev, dig->afmt->pin, 0); | |
| 493 | − dig->afmt->pin = NULL; | |
| 477 | + radeon_audio_enable(rdev, dig->pin, 0); | |
| 478 | + dig->pin = NULL; | |
| 494 | 479 | } |
| 495 | 480 | } |
| 496 | 481 | |
| @@ -518,29 +503,18 @@ static void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock · 21 unmodified lines | ||
| 518 | 503 | } |
| 519 | 504 | |
| 520 | 505 | static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, |
| 521 | − struct drm_display_mode *mode) | |
| 506 | + struct drm_display_mode *mode) | |
| 522 | 507 | { |
| 523 | 508 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 524 | 509 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 525 | 510 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 526 | − struct drm_connector *connector; | |
| 527 | − struct radeon_connector *radeon_connector = NULL; | |
| 511 | + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |
| 528 | 512 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; |
| 529 | 513 | struct hdmi_avi_infoframe frame; |
| 530 | 514 | int err; |
| 531 | 515 | |
| 532 | − list_for_each_entry(connector, | |
| 533 | − &encoder->dev->mode_config.connector_list, head) { | |
| 534 | − if (connector->encoder == encoder) { | |
| 535 | − radeon_connector = to_radeon_connector(connector); | |
| 536 | − break; | |
| 537 | − } | |
| 538 | − } | |
| 539 | − | |
| 540 | − if (!radeon_connector) { | |
| 541 | − DRM_ERROR("Couldn't find encoder's connector\n"); | |
| 542 | − return -ENOENT; | |
| 543 | − } | |
| 516 | + if (!connector) | |
| 517 | + return -EINVAL; | |
| 544 | 518 | |
| 545 | 519 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); |
| 546 | 520 | if (err < 0) { |
| @@ -563,8 +537,8 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, · 16 unmodified lines | ||
| 563 | 537 | return err; |
| 564 | 538 | } |
| 565 | 539 | |
| 566 | − if (dig && dig->afmt && | |
| 567 | − radeon_encoder->audio && radeon_encoder->audio->set_avi_packet) | |
| 540 | + if (dig && dig->afmt && radeon_encoder->audio && | |
| 541 | + radeon_encoder->audio->set_avi_packet) | |
| 568 | 542 | radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset, |
| 569 | 543 | buffer, sizeof(buffer)); |
| 570 | 544 | |
| @@ -722,30 +696,41 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, · 151 unmodified lines | ||
| 722 | 696 | { |
| 723 | 697 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 724 | 698 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 699 | + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |
| 725 | 700 | |
| 726 | 701 | if (!dig || !dig->afmt) |
| 727 | 702 | return; |
| 728 | 703 | |
| 729 | − radeon_audio_set_mute(encoder, true); | |
| 704 | + if (!connector) | |
| 705 | + return; | |
| 730 | 706 | |
| 731 | − radeon_audio_write_speaker_allocation(encoder); | |
| 732 | − radeon_audio_write_sad_regs(encoder); | |
| 733 | − radeon_audio_write_latency_fields(encoder, mode); | |
| 734 | − radeon_audio_set_dto(encoder, mode->clock); | |
| 735 | − radeon_audio_set_vbi_packet(encoder); | |
| 736 | − radeon_hdmi_set_color_depth(encoder); | |
| 737 | − radeon_audio_update_acr(encoder, mode->clock); | |
| 738 | − radeon_audio_set_audio_packet(encoder); | |
| 739 | − radeon_audio_select_pin(encoder); | |
| 707 | + if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { | |
| 708 | + radeon_audio_set_mute(encoder, true); | |
| 740 | 709 | |
| 741 | − if (radeon_audio_set_avi_packet(encoder, mode) < 0) | |
| 742 | − return; | |
| 710 | + radeon_audio_write_speaker_allocation(encoder); | |
| 711 | + radeon_audio_write_sad_regs(encoder); | |
| 712 | + radeon_audio_write_latency_fields(encoder, mode); | |
| 713 | + radeon_audio_set_dto(encoder, mode->clock); | |
| 714 | + radeon_audio_set_vbi_packet(encoder); | |
| 715 | + radeon_hdmi_set_color_depth(encoder); | |
| 716 | + radeon_audio_update_acr(encoder, mode->clock); | |
| 717 | + radeon_audio_set_audio_packet(encoder); | |
| 718 | + radeon_audio_select_pin(encoder); | |
| 719 | + | |
| 720 | + if (radeon_audio_set_avi_packet(encoder, mode) < 0) | |
| 721 | + return; | |
| 743 | 722 | |
| 744 | − radeon_audio_set_mute(encoder, false); | |
| 723 | + radeon_audio_set_mute(encoder, false); | |
| 724 | + } else { | |
| 725 | + radeon_hdmi_set_color_depth(encoder); | |
| 726 | + | |
| 727 | + if (radeon_audio_set_avi_packet(encoder, mode) < 0) | |
| 728 | + return; | |
| 729 | + } | |
| 745 | 730 | } |
| 746 | 731 | |
| 747 | 732 | static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, |
| 748 | − struct drm_display_mode *mode) | |
| 733 | + struct drm_display_mode *mode) | |
| 749 | 734 | { |
| 750 | 735 | struct drm_device *dev = encoder->dev; |
| 751 | 736 | struct radeon_device *rdev = dev->dev_private; |
| @@ -759,22 +744,27 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, · 7 unmodified lines | ||
| 759 | 744 | if (!dig || !dig->afmt) |
| 760 | 745 | return; |
| 761 | 746 | |
| 762 | − radeon_audio_write_speaker_allocation(encoder); | |
| 763 | − radeon_audio_write_sad_regs(encoder); | |
| 764 | − radeon_audio_write_latency_fields(encoder, mode); | |
| 765 | − if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev)) | |
| 766 | − radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); | |
| 767 | − else | |
| 768 | − radeon_audio_set_dto(encoder, dig_connector->dp_clock); | |
| 769 | − radeon_audio_set_audio_packet(encoder); | |
| 770 | − radeon_audio_select_pin(encoder); | |
| 771 | − | |
| 772 | − if (radeon_audio_set_avi_packet(encoder, mode) < 0) | |
| 747 | + if (!connector) | |
| 773 | 748 | return; |
| 749 | + | |
| 750 | + if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { | |
| 751 | + radeon_audio_write_speaker_allocation(encoder); | |
| 752 | + radeon_audio_write_sad_regs(encoder); | |
| 753 | + radeon_audio_write_latency_fields(encoder, mode); | |
| 754 | + if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev)) | |
| 755 | + radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); | |
| 756 | + else | |
| 757 | + radeon_audio_set_dto(encoder, dig_connector->dp_clock); | |
| 758 | + radeon_audio_set_audio_packet(encoder); | |
| 759 | + radeon_audio_select_pin(encoder); | |
| 760 | + | |
| 761 | + if (radeon_audio_set_avi_packet(encoder, mode) < 0) | |
| 762 | + return; | |
| 763 | + } | |
| 774 | 764 | } |
| 775 | 765 | |
| 776 | 766 | void radeon_audio_mode_set(struct drm_encoder *encoder, |
| 777 | − struct drm_display_mode *mode) | |
| 767 | + struct drm_display_mode *mode) | |
| 778 | 768 | { |
| 779 | 769 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 780 | 770 | |
| @@ -68,7 +68,8 @@ struct radeon_audio_funcs · 67 unmodified lines | ||
| 68 | 68 | |
| 69 | 69 | int radeon_audio_init(struct radeon_device *rdev); |
| 70 | 70 | void radeon_audio_detect(struct drm_connector *connector, |
| 71 | − enum drm_connector_status status); | |
| 71 | + struct drm_encoder *encoder, | |
| 72 | + enum drm_connector_status status); | |
| 72 | 73 | u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, |
| 73 | 74 | u32 offset, u32 reg); |
| 74 | 75 | void radeon_audio_endpoint_wreg(struct radeon_device *rdev, |
| @@ -1255,10 +1255,15 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder · 1254 unmodified lines | ||
| 1255 | 1255 | |
| 1256 | 1256 | if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) && |
| 1257 | 1257 | (RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) { |
| 1258 | + u32 hss = (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; | |
| 1259 | + | |
| 1260 | + if (hss > lvds->native_mode.hdisplay) | |
| 1261 | + hss = (10 - 1) * 8; | |
| 1262 | + | |
| 1258 | 1263 | lvds->native_mode.htotal = lvds->native_mode.hdisplay + |
| 1259 | 1264 | (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8; |
| 1260 | 1265 | lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + |
| 1261 | − (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; | |
| 1266 | + hss; | |
| 1262 | 1267 | lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + |
| 1263 | 1268 | (RBIOS8(tmp + 23) * 8); |
| 1264 | 1269 | |
| @@ -1379,8 +1379,16 @@ out: · 1378 unmodified lines | ||
| 1379 | 1379 | /* updated in get modes as well since we need to know if it's analog or digital */ |
| 1380 | 1380 | radeon_connector_update_scratch_regs(connector, ret); |
| 1381 | 1381 | |
| 1382 | − if (radeon_audio != 0) | |
| 1383 | − radeon_audio_detect(connector, ret); | |
| 1382 | + if ((radeon_audio != 0) && radeon_connector->use_digital) { | |
| 1383 | + const struct drm_connector_helper_funcs *connector_funcs = | |
| 1384 | + connector->helper_private; | |
| 1385 | + | |
| 1386 | + encoder = connector_funcs->best_encoder(connector); | |
| 1387 | + if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) { | |
| 1388 | + radeon_connector_get_edid(connector); | |
| 1389 | + radeon_audio_detect(connector, encoder, ret); | |
| 1390 | + } | |
| 1391 | + } | |
| 1384 | 1392 | |
| 1385 | 1393 | exit: |
| 1386 | 1394 | pm_runtime_mark_last_busy(connector->dev->dev); |
| @@ -1717,8 +1725,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force) · 330 unmodified lines | ||
| 1717 | 1725 | |
| 1718 | 1726 | radeon_connector_update_scratch_regs(connector, ret); |
| 1719 | 1727 | |
| 1720 | − if (radeon_audio != 0) | |
| 1721 | − radeon_audio_detect(connector, ret); | |
| 1728 | + if ((radeon_audio != 0) && encoder) { | |
| 1729 | + radeon_connector_get_edid(connector); | |
| 1730 | + radeon_audio_detect(connector, encoder, ret); | |
| 1731 | + } | |
| 1722 | 1732 | |
| 1723 | 1733 | out: |
| 1724 | 1734 | pm_runtime_mark_last_busy(connector->dev->dev); |
| @@ -237,7 +237,6 @@ struct radeon_afmt { · 236 unmodified lines | ||
| 237 | 237 | int offset; |
| 238 | 238 | bool last_buffer_filled_status; |
| 239 | 239 | int id; |
| 240 | − struct r600_audio_pin *pin; | |
| 241 | 240 | }; |
| 242 | 241 | |
| 243 | 242 | struct radeon_mode_info { |
| @@ -439,6 +438,7 @@ struct radeon_encoder_atom_dig { · 195 unmodified lines | ||
| 439 | 438 | uint8_t backlight_level; |
| 440 | 439 | int panel_mode; |
| 441 | 440 | struct radeon_afmt *afmt; |
| 441 | + struct r600_audio_pin *pin; | |
| 442 | 442 | int active_mst_links; |
| 443 | 443 | }; |
| 444 | 444 | |
| @@ -32,7 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | #ifndef __AMDGPU_DRM_H__ |
| 33 | 33 | #define __AMDGPU_DRM_H__ |
| 34 | 34 | |
| 35 | −#include <drm/drm.h> | |
| 35 | +#include "drm.h" | |
| 36 | 36 | |
| 37 | 37 | #define DRM_AMDGPU_GEM_CREATE 0x00 |
| 38 | 38 | #define DRM_AMDGPU_GEM_MMAP 0x01 |
| @@ -33,7 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #ifndef __RADEON_DRM_H__ |
| 34 | 34 | #define __RADEON_DRM_H__ |
| 35 | 35 | |
| 36 | −#include <drm/drm.h> | |
| 36 | +#include "drm.h" | |
| 37 | 37 | |
| 38 | 38 | /* WARNING: If you change any of these defines, make sure to change the |
| 39 | 39 | * defines in the X server file (radeon_sarea.h) |