diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-31 15:05:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-31 15:05:02 -0400 |
commit | fd56d1d66afce096f643faedfe1505488bdf1edd (patch) | |
tree | 9f51e6bd3fb8187695e9680b880c87da94a63280 | |
parent | 8400935737bf02d97da281bdcd139a421624b6ba (diff) | |
parent | bdce3e7c729907e303396690b2b23b972c6717be (diff) |
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
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
...
43 files changed, 554 insertions, 274 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e9fde72cf038..31b00f91cfcd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -1866,6 +1866,12 @@ typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t); | |||
1866 | typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t); | 1866 | typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t); |
1867 | typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t); | 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 | struct amdgpu_device { | 1875 | struct amdgpu_device { |
1870 | struct device *dev; | 1876 | struct device *dev; |
1871 | struct drm_device *ddev; | 1877 | struct drm_device *ddev; |
@@ -2008,7 +2014,7 @@ struct amdgpu_device { | |||
2008 | 2014 | ||
2009 | const struct amdgpu_ip_block_version *ip_blocks; | 2015 | const struct amdgpu_ip_block_version *ip_blocks; |
2010 | int num_ip_blocks; | 2016 | int num_ip_blocks; |
2011 | bool *ip_block_enabled; | 2017 | struct amdgpu_ip_block_status *ip_block_status; |
2012 | struct mutex mn_lock; | 2018 | struct mutex mn_lock; |
2013 | DECLARE_HASHTABLE(mn_hash, 7); | 2019 | DECLARE_HASHTABLE(mn_hash, 7); |
2014 | 2020 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d79009b65867..99f158e1baff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -1191,8 +1191,9 @@ static int amdgpu_early_init(struct amdgpu_device *adev) | |||
1191 | return -EINVAL; | 1191 | return -EINVAL; |
1192 | } | 1192 | } |
1193 | 1193 | ||
1194 | adev->ip_block_enabled = kcalloc(adev->num_ip_blocks, sizeof(bool), GFP_KERNEL); | 1194 | adev->ip_block_status = kcalloc(adev->num_ip_blocks, |
1195 | if (adev->ip_block_enabled == NULL) | 1195 | sizeof(struct amdgpu_ip_block_status), GFP_KERNEL); |
1196 | if (adev->ip_block_status == NULL) | ||
1196 | return -ENOMEM; | 1197 | return -ENOMEM; |
1197 | 1198 | ||
1198 | if (adev->ip_blocks == NULL) { | 1199 | if (adev->ip_blocks == NULL) { |
@@ -1203,18 +1204,18 @@ static int amdgpu_early_init(struct amdgpu_device *adev) | |||
1203 | for (i = 0; i < adev->num_ip_blocks; i++) { | 1204 | for (i = 0; i < adev->num_ip_blocks; i++) { |
1204 | if ((amdgpu_ip_block_mask & (1 << i)) == 0) { | 1205 | if ((amdgpu_ip_block_mask & (1 << i)) == 0) { |
1205 | DRM_ERROR("disabled ip block: %d\n", i); | 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 | } else { | 1208 | } else { |
1208 | if (adev->ip_blocks[i].funcs->early_init) { | 1209 | if (adev->ip_blocks[i].funcs->early_init) { |
1209 | r = adev->ip_blocks[i].funcs->early_init((void *)adev); | 1210 | r = adev->ip_blocks[i].funcs->early_init((void *)adev); |
1210 | if (r == -ENOENT) | 1211 | if (r == -ENOENT) |
1211 | adev->ip_block_enabled[i] = false; | 1212 | adev->ip_block_status[i].valid = false; |
1212 | else if (r) | 1213 | else if (r) |
1213 | return r; | 1214 | return r; |
1214 | else | 1215 | else |
1215 | adev->ip_block_enabled[i] = true; | 1216 | adev->ip_block_status[i].valid = true; |
1216 | } else { | 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) | |||
1227 | int i, r; | 1228 | int i, r; |
1228 | 1229 | ||
1229 | for (i = 0; i < adev->num_ip_blocks; i++) { | 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 | continue; | 1232 | continue; |
1232 | r = adev->ip_blocks[i].funcs->sw_init((void *)adev); | 1233 | r = adev->ip_blocks[i].funcs->sw_init((void *)adev); |
1233 | if (r) | 1234 | if (r) |
1234 | return r; | 1235 | return r; |
1236 | adev->ip_block_status[i].sw = true; | ||
1235 | /* need to do gmc hw init early so we can allocate gpu mem */ | 1237 | /* need to do gmc hw init early so we can allocate gpu mem */ |
1236 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { | 1238 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { |
1237 | r = amdgpu_vram_scratch_init(adev); | 1239 | r = amdgpu_vram_scratch_init(adev); |
@@ -1243,11 +1245,12 @@ static int amdgpu_init(struct amdgpu_device *adev) | |||
1243 | r = amdgpu_wb_init(adev); | 1245 | r = amdgpu_wb_init(adev); |
1244 | if (r) | 1246 | if (r) |
1245 | return r; | 1247 | return r; |
1248 | adev->ip_block_status[i].hw = true; | ||
1246 | } | 1249 | } |
1247 | } | 1250 | } |
1248 | 1251 | ||
1249 | for (i = 0; i < adev->num_ip_blocks; i++) { | 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 | continue; | 1254 | continue; |
1252 | /* gmc hw init is done early */ | 1255 | /* gmc hw init is done early */ |
1253 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) | 1256 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) |
@@ -1255,6 +1258,7 @@ static int amdgpu_init(struct amdgpu_device *adev) | |||
1255 | r = adev->ip_blocks[i].funcs->hw_init((void *)adev); | 1258 | r = adev->ip_blocks[i].funcs->hw_init((void *)adev); |
1256 | if (r) | 1259 | if (r) |
1257 | return r; | 1260 | return r; |
1261 | adev->ip_block_status[i].hw = true; | ||
1258 | } | 1262 | } |
1259 | 1263 | ||
1260 | return 0; | 1264 | return 0; |
@@ -1265,7 +1269,7 @@ static int amdgpu_late_init(struct amdgpu_device *adev) | |||
1265 | int i = 0, r; | 1269 | int i = 0, r; |
1266 | 1270 | ||
1267 | for (i = 0; i < adev->num_ip_blocks; i++) { | 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 | continue; | 1273 | continue; |
1270 | /* enable clockgating to save power */ | 1274 | /* enable clockgating to save power */ |
1271 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | 1275 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, |
@@ -1287,7 +1291,7 @@ static int amdgpu_fini(struct amdgpu_device *adev) | |||
1287 | int i, r; | 1291 | int i, r; |
1288 | 1292 | ||
1289 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | 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 | continue; | 1295 | continue; |
1292 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { | 1296 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { |
1293 | amdgpu_wb_fini(adev); | 1297 | amdgpu_wb_fini(adev); |
@@ -1300,14 +1304,16 @@ static int amdgpu_fini(struct amdgpu_device *adev) | |||
1300 | return r; | 1304 | return r; |
1301 | r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); | 1305 | r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); |
1302 | /* XXX handle errors */ | 1306 | /* XXX handle errors */ |
1307 | adev->ip_block_status[i].hw = false; | ||
1303 | } | 1308 | } |
1304 | 1309 | ||
1305 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | 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 | continue; | 1312 | continue; |
1308 | r = adev->ip_blocks[i].funcs->sw_fini((void *)adev); | 1313 | r = adev->ip_blocks[i].funcs->sw_fini((void *)adev); |
1309 | /* XXX handle errors */ | 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 | return 0; | 1319 | return 0; |
@@ -1318,7 +1324,7 @@ static int amdgpu_suspend(struct amdgpu_device *adev) | |||
1318 | int i, r; | 1324 | int i, r; |
1319 | 1325 | ||
1320 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | 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 | continue; | 1328 | continue; |
1323 | /* ungate blocks so that suspend can properly shut them down */ | 1329 | /* ungate blocks so that suspend can properly shut them down */ |
1324 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | 1330 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, |
@@ -1336,7 +1342,7 @@ static int amdgpu_resume(struct amdgpu_device *adev) | |||
1336 | int i, r; | 1342 | int i, r; |
1337 | 1343 | ||
1338 | for (i = 0; i < adev->num_ip_blocks; i++) { | 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 | continue; | 1346 | continue; |
1341 | r = adev->ip_blocks[i].funcs->resume(adev); | 1347 | r = adev->ip_blocks[i].funcs->resume(adev); |
1342 | if (r) | 1348 | if (r) |
@@ -1582,8 +1588,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) | |||
1582 | amdgpu_fence_driver_fini(adev); | 1588 | amdgpu_fence_driver_fini(adev); |
1583 | amdgpu_fbdev_fini(adev); | 1589 | amdgpu_fbdev_fini(adev); |
1584 | r = amdgpu_fini(adev); | 1590 | r = amdgpu_fini(adev); |
1585 | kfree(adev->ip_block_enabled); | 1591 | kfree(adev->ip_block_status); |
1586 | adev->ip_block_enabled = NULL; | 1592 | adev->ip_block_status = NULL; |
1587 | adev->accel_working = false; | 1593 | adev->accel_working = false; |
1588 | /* free i2c buses */ | 1594 | /* free i2c buses */ |
1589 | amdgpu_i2c_fini(adev); | 1595 | amdgpu_i2c_fini(adev); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index ae43b58c9733..4afc507820c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
@@ -449,7 +449,7 @@ out: | |||
449 | * vital here, so they are not reported back to userspace. | 449 | * vital here, so they are not reported back to userspace. |
450 | */ | 450 | */ |
451 | static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, | 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 | struct ttm_validate_buffer tv, *entry; | 454 | struct ttm_validate_buffer tv, *entry; |
455 | struct amdgpu_bo_list_entry *vm_bos; | 455 | struct amdgpu_bo_list_entry *vm_bos; |
@@ -485,7 +485,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, | |||
485 | if (r) | 485 | if (r) |
486 | goto error_unlock; | 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 | error_unlock: | 492 | error_unlock: |
491 | mutex_unlock(&bo_va->vm->mutex); | 493 | mutex_unlock(&bo_va->vm->mutex); |
@@ -580,7 +582,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, | |||
580 | } | 582 | } |
581 | 583 | ||
582 | if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE)) | 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 | drm_gem_object_unreference_unlocked(gobj); | 587 | drm_gem_object_unreference_unlocked(gobj); |
586 | return r; | 588 | return r; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 52dff75aac6f..bc0fac618a3f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | |||
@@ -180,16 +180,16 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, | |||
180 | if (vm) { | 180 | if (vm) { |
181 | /* do context switch */ | 181 | /* do context switch */ |
182 | amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update); | 182 | amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update); |
183 | } | ||
184 | 183 | ||
185 | if (vm && ring->funcs->emit_gds_switch) | 184 | if (ring->funcs->emit_gds_switch) |
186 | amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, | 185 | amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, |
187 | ib->gds_base, ib->gds_size, | 186 | ib->gds_base, ib->gds_size, |
188 | ib->gws_base, ib->gws_size, | 187 | ib->gws_base, ib->gws_size, |
189 | ib->oa_base, ib->oa_size); | 188 | ib->oa_base, ib->oa_size); |
190 | 189 | ||
191 | if (ring->funcs->emit_hdp_flush) | 190 | if (ring->funcs->emit_hdp_flush) |
192 | amdgpu_ring_emit_hdp_flush(ring); | 191 | amdgpu_ring_emit_hdp_flush(ring); |
192 | } | ||
193 | 193 | ||
194 | old_ctx = ring->current_ctx; | 194 | old_ctx = ring->current_ctx; |
195 | for (i = 0; i < num_ibs; ++i) { | 195 | for (i = 0; i < num_ibs; ++i) { |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 31ad444c6386..9736892bcdf9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | |||
@@ -235,7 +235,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file | |||
235 | 235 | ||
236 | for (i = 0; i < adev->num_ip_blocks; i++) { | 236 | for (i = 0; i < adev->num_ip_blocks; i++) { |
237 | if (adev->ip_blocks[i].type == type && | 237 | if (adev->ip_blocks[i].type == type && |
238 | adev->ip_block_enabled[i]) { | 238 | adev->ip_block_status[i].valid) { |
239 | ip.hw_ip_version_major = adev->ip_blocks[i].major; | 239 | ip.hw_ip_version_major = adev->ip_blocks[i].major; |
240 | ip.hw_ip_version_minor = adev->ip_blocks[i].minor; | 240 | ip.hw_ip_version_minor = adev->ip_blocks[i].minor; |
241 | ip.capabilities_flags = 0; | 241 | ip.capabilities_flags = 0; |
@@ -274,7 +274,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file | |||
274 | 274 | ||
275 | for (i = 0; i < adev->num_ip_blocks; i++) | 275 | for (i = 0; i < adev->num_ip_blocks; i++) |
276 | if (adev->ip_blocks[i].type == type && | 276 | if (adev->ip_blocks[i].type == type && |
277 | adev->ip_block_enabled[i] && | 277 | adev->ip_block_status[i].valid && |
278 | count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT) | 278 | count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT) |
279 | count++; | 279 | count++; |
280 | 280 | ||
@@ -416,7 +416,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file | |||
416 | return n ? -EFAULT : 0; | 416 | return n ? -EFAULT : 0; |
417 | } | 417 | } |
418 | case AMDGPU_INFO_DEV_INFO: { | 418 | case AMDGPU_INFO_DEV_INFO: { |
419 | struct drm_amdgpu_info_device dev_info; | 419 | struct drm_amdgpu_info_device dev_info = {}; |
420 | struct amdgpu_cu_info cu_info; | 420 | struct amdgpu_cu_info cu_info; |
421 | 421 | ||
422 | dev_info.device_id = dev->pdev->device; | 422 | dev_info.device_id = dev->pdev->device; |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 2c188fb9fd22..2db6ab0a543d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | |||
@@ -2561,7 +2561,7 @@ static bool gfx_v7_0_ring_emit_semaphore(struct amdgpu_ring *ring, | |||
2561 | * sheduling on the ring. This function schedules the IB | 2561 | * sheduling on the ring. This function schedules the IB |
2562 | * on the gfx ring for execution by the GPU. | 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 | struct amdgpu_ib *ib) | 2565 | struct amdgpu_ib *ib) |
2566 | { | 2566 | { |
2567 | bool need_ctx_switch = ring->current_ctx != ib->ctx; | 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, | |||
2569 | u32 next_rptr = ring->wptr + 5; | 2569 | u32 next_rptr = ring->wptr + 5; |
2570 | 2570 | ||
2571 | /* drop the CE preamble IB for the same context */ | 2571 | /* drop the CE preamble IB for the same context */ |
2572 | if ((ring->type == AMDGPU_RING_TYPE_GFX) && | 2572 | if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch) |
2573 | (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && | ||
2574 | !need_ctx_switch) | ||
2575 | return; | 2573 | return; |
2576 | 2574 | ||
2577 | if (ring->type == AMDGPU_RING_TYPE_COMPUTE) | 2575 | if (need_ctx_switch) |
2578 | control |= INDIRECT_BUFFER_VALID; | ||
2579 | |||
2580 | if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) | ||
2581 | next_rptr += 2; | 2576 | next_rptr += 2; |
2582 | 2577 | ||
2583 | next_rptr += 4; | 2578 | next_rptr += 4; |
@@ -2588,7 +2583,7 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, | |||
2588 | amdgpu_ring_write(ring, next_rptr); | 2583 | amdgpu_ring_write(ring, next_rptr); |
2589 | 2584 | ||
2590 | /* insert SWITCH_BUFFER packet before first IB in the ring frame */ | 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 | amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); | 2587 | amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); |
2593 | amdgpu_ring_write(ring, 0); | 2588 | amdgpu_ring_write(ring, 0); |
2594 | } | 2589 | } |
@@ -2611,6 +2606,35 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, | |||
2611 | amdgpu_ring_write(ring, control); | 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 | * gfx_v7_0_ring_test_ib - basic ring IB test | 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 = { | |||
5555 | .get_wptr = gfx_v7_0_ring_get_wptr_gfx, | 5579 | .get_wptr = gfx_v7_0_ring_get_wptr_gfx, |
5556 | .set_wptr = gfx_v7_0_ring_set_wptr_gfx, | 5580 | .set_wptr = gfx_v7_0_ring_set_wptr_gfx, |
5557 | .parse_cs = NULL, | 5581 | .parse_cs = NULL, |
5558 | .emit_ib = gfx_v7_0_ring_emit_ib, | 5582 | .emit_ib = gfx_v7_0_ring_emit_ib_gfx, |
5559 | .emit_fence = gfx_v7_0_ring_emit_fence_gfx, | 5583 | .emit_fence = gfx_v7_0_ring_emit_fence_gfx, |
5560 | .emit_semaphore = gfx_v7_0_ring_emit_semaphore, | 5584 | .emit_semaphore = gfx_v7_0_ring_emit_semaphore, |
5561 | .emit_vm_flush = gfx_v7_0_ring_emit_vm_flush, | 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 = { | |||
5571 | .get_wptr = gfx_v7_0_ring_get_wptr_compute, | 5595 | .get_wptr = gfx_v7_0_ring_get_wptr_compute, |
5572 | .set_wptr = gfx_v7_0_ring_set_wptr_compute, | 5596 | .set_wptr = gfx_v7_0_ring_set_wptr_compute, |
5573 | .parse_cs = NULL, | 5597 | .parse_cs = NULL, |
5574 | .emit_ib = gfx_v7_0_ring_emit_ib, | 5598 | .emit_ib = gfx_v7_0_ring_emit_ib_compute, |
5575 | .emit_fence = gfx_v7_0_ring_emit_fence_compute, | 5599 | .emit_fence = gfx_v7_0_ring_emit_fence_compute, |
5576 | .emit_semaphore = gfx_v7_0_ring_emit_semaphore, | 5600 | .emit_semaphore = gfx_v7_0_ring_emit_semaphore, |
5577 | .emit_vm_flush = gfx_v7_0_ring_emit_vm_flush, | 5601 | .emit_vm_flush = gfx_v7_0_ring_emit_vm_flush, |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 1c7c992dea37..9e1d4ddbf475 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | |||
@@ -3753,7 +3753,7 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) | |||
3753 | amdgpu_ring_write(ring, 0x20); /* poll interval */ | 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 | struct amdgpu_ib *ib) | 3757 | struct amdgpu_ib *ib) |
3758 | { | 3758 | { |
3759 | bool need_ctx_switch = ring->current_ctx != ib->ctx; | 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, | |||
3761 | u32 next_rptr = ring->wptr + 5; | 3761 | u32 next_rptr = ring->wptr + 5; |
3762 | 3762 | ||
3763 | /* drop the CE preamble IB for the same context */ | 3763 | /* drop the CE preamble IB for the same context */ |
3764 | if ((ring->type == AMDGPU_RING_TYPE_GFX) && | 3764 | if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch) |
3765 | (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && | ||
3766 | !need_ctx_switch) | ||
3767 | return; | 3765 | return; |
3768 | 3766 | ||
3769 | if (ring->type == AMDGPU_RING_TYPE_COMPUTE) | 3767 | if (need_ctx_switch) |
3770 | control |= INDIRECT_BUFFER_VALID; | ||
3771 | |||
3772 | if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) | ||
3773 | next_rptr += 2; | 3768 | next_rptr += 2; |
3774 | 3769 | ||
3775 | next_rptr += 4; | 3770 | next_rptr += 4; |
@@ -3780,7 +3775,7 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, | |||
3780 | amdgpu_ring_write(ring, next_rptr); | 3775 | amdgpu_ring_write(ring, next_rptr); |
3781 | 3776 | ||
3782 | /* insert SWITCH_BUFFER packet before first IB in the ring frame */ | 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 | amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); | 3779 | amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); |
3785 | amdgpu_ring_write(ring, 0); | 3780 | amdgpu_ring_write(ring, 0); |
3786 | } | 3781 | } |
@@ -3803,6 +3798,36 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, | |||
3803 | amdgpu_ring_write(ring, control); | 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 | static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, | 3831 | static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, |
3807 | u64 seq, unsigned flags) | 3832 | u64 seq, unsigned flags) |
3808 | { | 3833 | { |
@@ -4224,7 +4249,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { | |||
4224 | .get_wptr = gfx_v8_0_ring_get_wptr_gfx, | 4249 | .get_wptr = gfx_v8_0_ring_get_wptr_gfx, |
4225 | .set_wptr = gfx_v8_0_ring_set_wptr_gfx, | 4250 | .set_wptr = gfx_v8_0_ring_set_wptr_gfx, |
4226 | .parse_cs = NULL, | 4251 | .parse_cs = NULL, |
4227 | .emit_ib = gfx_v8_0_ring_emit_ib, | 4252 | .emit_ib = gfx_v8_0_ring_emit_ib_gfx, |
4228 | .emit_fence = gfx_v8_0_ring_emit_fence_gfx, | 4253 | .emit_fence = gfx_v8_0_ring_emit_fence_gfx, |
4229 | .emit_semaphore = gfx_v8_0_ring_emit_semaphore, | 4254 | .emit_semaphore = gfx_v8_0_ring_emit_semaphore, |
4230 | .emit_vm_flush = gfx_v8_0_ring_emit_vm_flush, | 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 = { | |||
4240 | .get_wptr = gfx_v8_0_ring_get_wptr_compute, | 4265 | .get_wptr = gfx_v8_0_ring_get_wptr_compute, |
4241 | .set_wptr = gfx_v8_0_ring_set_wptr_compute, | 4266 | .set_wptr = gfx_v8_0_ring_set_wptr_compute, |
4242 | .parse_cs = NULL, | 4267 | .parse_cs = NULL, |
4243 | .emit_ib = gfx_v8_0_ring_emit_ib, | 4268 | .emit_ib = gfx_v8_0_ring_emit_ib_compute, |
4244 | .emit_fence = gfx_v8_0_ring_emit_fence_compute, | 4269 | .emit_fence = gfx_v8_0_ring_emit_fence_compute, |
4245 | .emit_semaphore = gfx_v8_0_ring_emit_semaphore, | 4270 | .emit_semaphore = gfx_v8_0_ring_emit_semaphore, |
4246 | .emit_vm_flush = gfx_v8_0_ring_emit_vm_flush, | 4271 | .emit_vm_flush = gfx_v8_0_ring_emit_vm_flush, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 0d1dbb737933..247a424445f7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | |||
@@ -220,13 +220,15 @@ static int mdp4_plane_mode_set(struct drm_plane *plane, | |||
220 | uint32_t op_mode = 0; | 220 | uint32_t op_mode = 0; |
221 | uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT; | 221 | uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT; |
222 | uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT; | 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 | if (!(crtc && fb)) { | 225 | if (!(crtc && fb)) { |
226 | DBG("%s: disabled!", mdp4_plane->name); | 226 | DBG("%s: disabled!", mdp4_plane->name); |
227 | return 0; | 227 | return 0; |
228 | } | 228 | } |
229 | 229 | ||
230 | frame_type = mdp4_get_frame_format(fb); | ||
231 | |||
230 | /* src values are in Q16 fixed point, convert to integer: */ | 232 | /* src values are in Q16 fixed point, convert to integer: */ |
231 | src_x = src_x >> 16; | 233 | src_x = src_x >> 16; |
232 | src_y = src_y >> 16; | 234 | src_y = src_y >> 16; |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 206f758f7d64..e253db5de5aa 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | |||
@@ -76,7 +76,20 @@ static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *st | |||
76 | 76 | ||
77 | static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) | 77 | static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) |
78 | { | 78 | { |
79 | int i; | ||
79 | struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); | 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 | mdp5_disable(mdp5_kms); | 93 | mdp5_disable(mdp5_kms); |
81 | } | 94 | } |
82 | 95 | ||
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h index e0eb24587c84..e79ac09b7216 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | |||
@@ -227,6 +227,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane, | |||
227 | struct drm_mode_object *obj); | 227 | struct drm_mode_object *obj); |
228 | uint32_t mdp5_plane_get_flush(struct drm_plane *plane); | 228 | uint32_t mdp5_plane_get_flush(struct drm_plane *plane); |
229 | void mdp5_plane_complete_flip(struct drm_plane *plane); | 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 | enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane); | 232 | enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane); |
231 | struct drm_plane *mdp5_plane_init(struct drm_device *dev, | 233 | struct drm_plane *mdp5_plane_init(struct drm_device *dev, |
232 | enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset); | 234 | enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset); |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 57b8f56ae9d0..22275568ab8b 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | |||
@@ -31,8 +31,6 @@ struct mdp5_plane { | |||
31 | 31 | ||
32 | uint32_t nformats; | 32 | uint32_t nformats; |
33 | uint32_t formats[32]; | 33 | uint32_t formats[32]; |
34 | |||
35 | bool enabled; | ||
36 | }; | 34 | }; |
37 | #define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base) | 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) | |||
56 | return state->fb && state->crtc; | 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 | static void mdp5_plane_destroy(struct drm_plane *plane) | 57 | static void mdp5_plane_destroy(struct drm_plane *plane) |
76 | { | 58 | { |
77 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); | 59 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); |
@@ -224,7 +206,6 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, | |||
224 | 206 | ||
225 | if (!plane_enabled(state)) { | 207 | if (!plane_enabled(state)) { |
226 | to_mdp5_plane_state(state)->pending = true; | 208 | to_mdp5_plane_state(state)->pending = true; |
227 | mdp5_plane_disable(plane); | ||
228 | } else if (to_mdp5_plane_state(state)->mode_changed) { | 209 | } else if (to_mdp5_plane_state(state)->mode_changed) { |
229 | int ret; | 210 | int ret; |
230 | to_mdp5_plane_state(state)->pending = true; | 211 | to_mdp5_plane_state(state)->pending = true; |
@@ -602,6 +583,20 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane) | |||
602 | return mdp5_plane->flush_mask; | 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 | /* initialize plane */ | 600 | /* initialize plane */ |
606 | struct drm_plane *mdp5_plane_init(struct drm_device *dev, | 601 | struct drm_plane *mdp5_plane_init(struct drm_device *dev, |
607 | enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset) | 602 | enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset) |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c index 16702aecf0df..64a27d86f2f5 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c | |||
@@ -34,22 +34,44 @@ | |||
34 | * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0). | 34 | * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0). |
35 | * | 35 | * |
36 | * For each block that can be dynamically allocated, it can be either | 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 | * 1) mdp5_smp_request(): | 52 | * 1) mdp5_smp_request(): |
40 | * When plane scanout is setup, calculate required number of | 53 | * When plane scanout is setup, calculate required number of |
41 | * blocks needed per client, and request. Blocks not inuse or | 54 | * blocks needed per client, and request. Blocks neither inuse nor |
42 | * pending by any other client are added to client's pending | 55 | * configured nor pending by any other client are added to client's |
43 | * set. | 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 | * 2) mdp5_smp_configure(): | 61 | * 2) mdp5_smp_configure(): |
46 | * As hw is programmed, before FLUSH, MDP5_MDP_SMP_ALLOC registers | 62 | * As hw is programmed, before FLUSH, MDP5_MDP_SMP_ALLOC registers |
47 | * are configured for the union(pending, inuse) | 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 | * 3) mdp5_smp_commit(): | 68 | * 3) mdp5_smp_commit(): |
50 | * After next vblank, copy pending -> inuse. Optionally update | 69 | * After next vblank, copy configured -> inuse. Optionally update |
51 | * MDP5_SMP_ALLOC registers if there are newly unused blocks | 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 | * On the next vblank after changes have been committed to hw, the | 75 | * On the next vblank after changes have been committed to hw, the |
54 | * client's pending blocks become it's in-use blocks (and no-longer | 76 | * client's pending blocks become it's in-use blocks (and no-longer |
55 | * in-use blocks become available to other clients). | 77 | * in-use blocks become available to other clients). |
@@ -77,6 +99,9 @@ struct mdp5_smp { | |||
77 | struct mdp5_client_smp_state client_state[MAX_CLIENTS]; | 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 | static inline | 105 | static inline |
81 | struct mdp5_kms *get_kms(struct mdp5_smp *smp) | 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, | |||
149 | for (i = cur_nblks; i > nblks; i--) { | 174 | for (i = cur_nblks; i > nblks; i--) { |
150 | int blk = find_first_bit(ps->pending, cnt); | 175 | int blk = find_first_bit(ps->pending, cnt); |
151 | clear_bit(blk, ps->pending); | 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 | |||
223 | /* Release SMP blocks for all clients of the pipe */ | 253 | /* Release SMP blocks for all clients of the pipe */ |
224 | void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe) | 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 | set_fifo_thresholds(smp, pipe, 0); | 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) | |||
274 | u32 cid = pipe2client(pipe, i); | 327 | u32 cid = pipe2client(pipe, i); |
275 | struct mdp5_client_smp_state *ps = &smp->client_state[cid]; | 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 | update_smp_state(smp, cid, &assigned); | 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 | void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) | 344 | void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) |
284 | { | 345 | { |
285 | int cnt = smp->blk_cnt; | 346 | int cnt = smp->blk_cnt; |
@@ -295,7 +356,7 @@ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) | |||
295 | * using, which can be released and made available to other | 356 | * using, which can be released and made available to other |
296 | * clients: | 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 | unsigned long flags; | 360 | unsigned long flags; |
300 | 361 | ||
301 | spin_lock_irqsave(&smp->state_lock, flags); | 362 | spin_lock_irqsave(&smp->state_lock, flags); |
@@ -306,7 +367,7 @@ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) | |||
306 | update_smp_state(smp, CID_UNUSED, &released); | 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 | ||
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h index e47179f63585..5b6c2363f592 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | struct mdp5_client_smp_state { | 24 | struct mdp5_client_smp_state { |
25 | mdp5_smp_state_t inuse; | 25 | mdp5_smp_state_t inuse; |
26 | mdp5_smp_state_t configured; | ||
26 | mdp5_smp_state_t pending; | 27 | mdp5_smp_state_t pending; |
27 | }; | 28 | }; |
28 | 29 | ||
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 1b22d8bfe142..1ceb4f22dd89 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c | |||
@@ -283,12 +283,8 @@ int msm_atomic_commit(struct drm_device *dev, | |||
283 | 283 | ||
284 | timeout = ktime_add_ms(ktime_get(), 1000); | 284 | timeout = ktime_add_ms(ktime_get(), 1000); |
285 | 285 | ||
286 | ret = msm_wait_fence_interruptable(dev, c->fence, &timeout); | 286 | /* uninterruptible wait */ |
287 | if (ret) { | 287 | msm_wait_fence(dev, c->fence, &timeout, false); |
288 | WARN_ON(ret); // TODO unswap state back? or?? | ||
289 | commit_destroy(c); | ||
290 | return ret; | ||
291 | } | ||
292 | 288 | ||
293 | complete_commit(c); | 289 | complete_commit(c); |
294 | 290 | ||
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index b7ef56ed8d1c..d3467b115e04 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c | |||
@@ -637,8 +637,8 @@ static void msm_debugfs_cleanup(struct drm_minor *minor) | |||
637 | * Fences: | 637 | * Fences: |
638 | */ | 638 | */ |
639 | 639 | ||
640 | int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, | 640 | int msm_wait_fence(struct drm_device *dev, uint32_t fence, |
641 | ktime_t *timeout) | 641 | ktime_t *timeout , bool interruptible) |
642 | { | 642 | { |
643 | struct msm_drm_private *priv = dev->dev_private; | 643 | struct msm_drm_private *priv = dev->dev_private; |
644 | int ret; | 644 | int ret; |
@@ -667,7 +667,12 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, | |||
667 | remaining_jiffies = timespec_to_jiffies(&ts); | 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 | fence_completed(dev, fence), | 676 | fence_completed(dev, fence), |
672 | remaining_jiffies); | 677 | remaining_jiffies); |
673 | 678 | ||
@@ -853,7 +858,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, | |||
853 | return -EINVAL; | 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 | static const struct drm_ioctl_desc msm_ioctls[] = { | 864 | static const struct drm_ioctl_desc msm_ioctls[] = { |
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index e7c5ea125d45..4ff0ec9c994b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h | |||
@@ -164,8 +164,8 @@ int msm_atomic_commit(struct drm_device *dev, | |||
164 | 164 | ||
165 | int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); | 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, | 167 | int msm_wait_fence(struct drm_device *dev, uint32_t fence, |
168 | ktime_t *timeout); | 168 | ktime_t *timeout, bool interruptible); |
169 | int msm_queue_fence_cb(struct drm_device *dev, | 169 | int msm_queue_fence_cb(struct drm_device *dev, |
170 | struct msm_fence_cb *cb, uint32_t fence); | 170 | struct msm_fence_cb *cb, uint32_t fence); |
171 | void msm_update_fence(struct drm_device *dev, uint32_t fence); | 171 | void msm_update_fence(struct drm_device *dev, uint32_t fence); |
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index f211b80e3a1e..c76cc853b08a 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c | |||
@@ -460,7 +460,7 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) | |||
460 | if (op & MSM_PREP_NOSYNC) | 460 | if (op & MSM_PREP_NOSYNC) |
461 | timeout = NULL; | 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 | /* TODO cache maintenance */ | 466 | /* TODO cache maintenance */ |
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index dd7a7ab603e2..831461bc98a5 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c | |||
@@ -23,8 +23,12 @@ | |||
23 | struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) | 23 | struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) |
24 | { | 24 | { |
25 | struct msm_gem_object *msm_obj = to_msm_bo(obj); | 25 | struct msm_gem_object *msm_obj = to_msm_bo(obj); |
26 | BUG_ON(!msm_obj->sgt); /* should have already pinned! */ | 26 | int npages = obj->size >> PAGE_SHIFT; |
27 | return msm_obj->sgt; | 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 | void *msm_gem_prime_vmap(struct drm_gem_object *obj) | 34 | void *msm_gem_prime_vmap(struct drm_gem_object *obj) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 649024d4daf1..477cbb12809b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -128,6 +128,7 @@ nouveau_cli_destroy(struct nouveau_cli *cli) | |||
128 | nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL); | 128 | nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL); |
129 | nvif_client_fini(&cli->base); | 129 | nvif_client_fini(&cli->base); |
130 | usif_client_fini(cli); | 130 | usif_client_fini(cli); |
131 | kfree(cli); | ||
131 | } | 132 | } |
132 | 133 | ||
133 | static void | 134 | static void |
@@ -865,8 +866,10 @@ nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv) | |||
865 | 866 | ||
866 | pm_runtime_get_sync(dev->dev); | 867 | pm_runtime_get_sync(dev->dev); |
867 | 868 | ||
869 | mutex_lock(&cli->mutex); | ||
868 | if (cli->abi16) | 870 | if (cli->abi16) |
869 | nouveau_abi16_fini(cli->abi16); | 871 | nouveau_abi16_fini(cli->abi16); |
872 | mutex_unlock(&cli->mutex); | ||
870 | 873 | ||
871 | mutex_lock(&drm->client.mutex); | 874 | mutex_lock(&drm->client.mutex); |
872 | list_del(&cli->head); | 875 | list_del(&cli->head); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index 775277f1edb0..dcfbbfaf1739 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c | |||
@@ -92,6 +92,8 @@ static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu) | |||
92 | return 0; | 92 | return 0; |
93 | } | 93 | } |
94 | 94 | ||
95 | #if IS_ENABLED(CONFIG_IOMMU_API) | ||
96 | |||
95 | static void nouveau_platform_probe_iommu(struct device *dev, | 97 | static void nouveau_platform_probe_iommu(struct device *dev, |
96 | struct nouveau_platform_gpu *gpu) | 98 | struct nouveau_platform_gpu *gpu) |
97 | { | 99 | { |
@@ -158,6 +160,20 @@ static void nouveau_platform_remove_iommu(struct device *dev, | |||
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 | static int nouveau_platform_probe(struct platform_device *pdev) | 177 | static int nouveau_platform_probe(struct platform_device *pdev) |
162 | { | 178 | { |
163 | struct nouveau_platform_gpu *gpu; | 179 | struct nouveau_platform_gpu *gpu; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 18f449715788..7464aef34674 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c | |||
@@ -175,15 +175,24 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, | |||
175 | node->page_shift = 12; | 175 | node->page_shift = 12; |
176 | 176 | ||
177 | switch (drm->device.info.family) { | 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 | case NV_DEVICE_INFO_V0_TESLA: | 184 | case NV_DEVICE_INFO_V0_TESLA: |
179 | if (drm->device.info.chipset != 0x50) | 185 | if (drm->device.info.chipset != 0x50) |
180 | node->memtype = (nvbo->tile_flags & 0x7f00) >> 8; | 186 | node->memtype = (nvbo->tile_flags & 0x7f00) >> 8; |
181 | break; | 187 | break; |
182 | case NV_DEVICE_INFO_V0_FERMI: | 188 | case NV_DEVICE_INFO_V0_FERMI: |
183 | case NV_DEVICE_INFO_V0_KEPLER: | 189 | case NV_DEVICE_INFO_V0_KEPLER: |
190 | case NV_DEVICE_INFO_V0_MAXWELL: | ||
184 | node->memtype = (nvbo->tile_flags & 0xff00) >> 8; | 191 | node->memtype = (nvbo->tile_flags & 0xff00) >> 8; |
185 | break; | 192 | break; |
186 | default: | 193 | default: |
194 | NV_WARN(drm, "%s: unhandled family type %x\n", __func__, | ||
195 | drm->device.info.family); | ||
187 | break; | 196 | break; |
188 | } | 197 | } |
189 | 198 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 4ef602c5469d..495c57644ced 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c | |||
@@ -203,7 +203,7 @@ nv04_fbcon_accel_init(struct fb_info *info) | |||
203 | if (ret) | 203 | if (ret) |
204 | return ret; | 204 | return ret; |
205 | 205 | ||
206 | if (RING_SPACE(chan, 49)) { | 206 | if (RING_SPACE(chan, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) { |
207 | nouveau_fbcon_gpu_lockup(info); | 207 | nouveau_fbcon_gpu_lockup(info); |
208 | return 0; | 208 | return 0; |
209 | } | 209 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 7da7958556a3..981342d142ff 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -979,7 +979,7 @@ nv50_crtc_cursor_show_hide(struct nouveau_crtc *nv_crtc, bool show, bool update) | |||
979 | { | 979 | { |
980 | struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); | 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 | nv50_crtc_cursor_show(nv_crtc); | 983 | nv50_crtc_cursor_show(nv_crtc); |
984 | else | 984 | else |
985 | nv50_crtc_cursor_hide(nv_crtc); | 985 | nv50_crtc_cursor_hide(nv_crtc); |
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 394c89abcc97..901130b06072 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c | |||
@@ -188,7 +188,7 @@ nv50_fbcon_accel_init(struct fb_info *info) | |||
188 | if (ret) | 188 | if (ret) |
189 | return ret; | 189 | return ret; |
190 | 190 | ||
191 | ret = RING_SPACE(chan, 59); | 191 | ret = RING_SPACE(chan, 58); |
192 | if (ret) { | 192 | if (ret) { |
193 | nouveau_fbcon_gpu_lockup(info); | 193 | nouveau_fbcon_gpu_lockup(info); |
194 | return ret; | 194 | return ret; |
@@ -252,6 +252,7 @@ nv50_fbcon_accel_init(struct fb_info *info) | |||
252 | OUT_RING(chan, info->var.yres_virtual); | 252 | OUT_RING(chan, info->var.yres_virtual); |
253 | OUT_RING(chan, upper_32_bits(fb->vma.offset)); | 253 | OUT_RING(chan, upper_32_bits(fb->vma.offset)); |
254 | OUT_RING(chan, lower_32_bits(fb->vma.offset)); | 254 | OUT_RING(chan, lower_32_bits(fb->vma.offset)); |
255 | FIRE_RING(chan); | ||
255 | 256 | ||
256 | return 0; | 257 | return 0; |
257 | } | 258 | } |
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c index 61246677e8dc..fcd2e5f27bb9 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c +++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c | |||
@@ -188,7 +188,7 @@ nvc0_fbcon_accel_init(struct fb_info *info) | |||
188 | return -EINVAL; | 188 | return -EINVAL; |
189 | } | 189 | } |
190 | 190 | ||
191 | ret = RING_SPACE(chan, 60); | 191 | ret = RING_SPACE(chan, 58); |
192 | if (ret) { | 192 | if (ret) { |
193 | WARN_ON(1); | 193 | WARN_ON(1); |
194 | nouveau_fbcon_gpu_lockup(info); | 194 | nouveau_fbcon_gpu_lockup(info); |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c index 9ef6728c528d..7f2f05f78cc8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c | |||
@@ -809,7 +809,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, | |||
809 | case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; | 809 | case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; |
810 | default: | 810 | default: |
811 | nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); | 811 | nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); |
812 | return 0x0000; | 812 | return NULL; |
813 | } | 813 | } |
814 | } | 814 | } |
815 | 815 | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index e10f9644140f..52c22b026005 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | |||
@@ -166,14 +166,30 @@ gk104_fifo_context_attach(struct nvkm_object *parent, | |||
166 | } | 166 | } |
167 | 167 | ||
168 | static int | 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 | |||
184 | static int | ||
169 | gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, | 185 | gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, |
170 | struct nvkm_object *object) | 186 | struct nvkm_object *object) |
171 | { | 187 | { |
172 | struct nvkm_bar *bar = nvkm_bar(parent); | 188 | struct nvkm_bar *bar = nvkm_bar(parent); |
173 | struct gk104_fifo_priv *priv = (void *)parent->engine; | ||
174 | struct gk104_fifo_base *base = (void *)parent->parent; | 189 | struct gk104_fifo_base *base = (void *)parent->parent; |
175 | struct gk104_fifo_chan *chan = (void *)parent; | 190 | struct gk104_fifo_chan *chan = (void *)parent; |
176 | u32 addr; | 191 | u32 addr; |
192 | int ret; | ||
177 | 193 | ||
178 | switch (nv_engidx(object->engine)) { | 194 | switch (nv_engidx(object->engine)) { |
179 | case NVDEV_ENGINE_SW : return 0; | 195 | case NVDEV_ENGINE_SW : return 0; |
@@ -188,13 +204,9 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, | |||
188 | return -EINVAL; | 204 | return -EINVAL; |
189 | } | 205 | } |
190 | 206 | ||
191 | nv_wr32(priv, 0x002634, chan->base.chid); | 207 | ret = gk104_fifo_chan_kick(chan); |
192 | if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { | 208 | if (ret && suspend) |
193 | nv_error(priv, "channel %d [%s] kick timeout\n", | 209 | return ret; |
194 | chan->base.chid, nvkm_client_name(chan)); | ||
195 | if (suspend) | ||
196 | return -EBUSY; | ||
197 | } | ||
198 | 210 | ||
199 | if (addr) { | 211 | if (addr) { |
200 | nv_wo32(base, addr + 0x00, 0x00000000); | 212 | nv_wo32(base, addr + 0x00, 0x00000000); |
@@ -319,6 +331,7 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend) | |||
319 | gk104_fifo_runlist_update(priv, chan->engine); | 331 | gk104_fifo_runlist_update(priv, chan->engine); |
320 | } | 332 | } |
321 | 333 | ||
334 | gk104_fifo_chan_kick(chan); | ||
322 | nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); | 335 | nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); |
323 | return nvkm_fifo_channel_fini(&chan->base, suspend); | 336 | return nvkm_fifo_channel_fini(&chan->base, suspend); |
324 | } | 337 | } |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 5606c25e5d02..ca11ddb6ed46 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | |||
@@ -663,6 +663,37 @@ gf100_gr_zbc_init(struct gf100_gr_priv *priv) | |||
663 | gf100_gr_zbc_clear_depth(priv, index); | 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 | void | 697 | void |
667 | gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) | 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) | |||
699 | 730 | ||
700 | while (addr < next) { | 731 | while (addr < next) { |
701 | nv_wr32(priv, 0x400200, addr); | 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 | addr += init->pitch; | 740 | addr += init->pitch; |
704 | } | 741 | } |
705 | } | 742 | } |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 8af1a89eda84..c9533fdac4fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | |||
@@ -181,6 +181,7 @@ struct gf100_gr_oclass { | |||
181 | int ppc_nr; | 181 | int ppc_nr; |
182 | }; | 182 | }; |
183 | 183 | ||
184 | int gf100_gr_wait_idle(struct gf100_gr_priv *); | ||
184 | void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *); | 185 | void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *); |
185 | void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *); | 186 | void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *); |
186 | void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *); | 187 | void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *); |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c index 2006c445938d..4cf36a3aa814 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c | |||
@@ -332,9 +332,12 @@ static void | |||
332 | nvkm_perfctx_dtor(struct nvkm_object *object) | 332 | nvkm_perfctx_dtor(struct nvkm_object *object) |
333 | { | 333 | { |
334 | struct nvkm_pm *ppm = (void *)object->engine; | 334 | struct nvkm_pm *ppm = (void *)object->engine; |
335 | struct nvkm_perfctx *ctx = (void *)object; | ||
336 | |||
335 | mutex_lock(&nv_subdev(ppm)->mutex); | 337 | mutex_lock(&nv_subdev(ppm)->mutex); |
336 | nvkm_engctx_destroy(&ppm->context->base); | 338 | nvkm_engctx_destroy(&ctx->base); |
337 | ppm->context = NULL; | 339 | if (ppm->context == ctx) |
340 | ppm->context = NULL; | ||
338 | mutex_unlock(&nv_subdev(ppm)->mutex); | 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, | |||
355 | mutex_lock(&nv_subdev(ppm)->mutex); | 358 | mutex_lock(&nv_subdev(ppm)->mutex); |
356 | if (ppm->context == NULL) | 359 | if (ppm->context == NULL) |
357 | ppm->context = ctx; | 360 | ppm->context = ctx; |
358 | mutex_unlock(&nv_subdev(ppm)->mutex); | ||
359 | |||
360 | if (ctx != ppm->context) | 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 | struct nvkm_oclass | 368 | struct nvkm_oclass |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index f67cdae1e90a..f4611e3f0971 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c | |||
@@ -1285,6 +1285,44 @@ init_zm_reg_sequence(struct nvbios_init *init) | |||
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | /** | 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 | |||
1325 | /** | ||
1288 | * INIT_SUB_DIRECT - opcode 0x5b | 1326 | * INIT_SUB_DIRECT - opcode 0x5b |
1289 | * | 1327 | * |
1290 | */ | 1328 | */ |
@@ -2145,6 +2183,8 @@ static struct nvbios_init_opcode { | |||
2145 | [0x56] = { init_condition_time }, | 2183 | [0x56] = { init_condition_time }, |
2146 | [0x57] = { init_ltime }, | 2184 | [0x57] = { init_ltime }, |
2147 | [0x58] = { init_zm_reg_sequence }, | 2185 | [0x58] = { init_zm_reg_sequence }, |
2186 | [0x59] = { init_pll_indirect }, | ||
2187 | [0x5a] = { init_zm_reg_indirect }, | ||
2148 | [0x5b] = { init_sub_direct }, | 2188 | [0x5b] = { init_sub_direct }, |
2149 | [0x5c] = { init_jump }, | 2189 | [0x5c] = { init_jump }, |
2150 | [0x5e] = { init_i2c_if }, | 2190 | [0x5e] = { init_i2c_if }, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c index 822d32a28d6e..065e9f5c8db9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c | |||
@@ -180,7 +180,8 @@ gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz, | |||
180 | struct gt215_clk_info *info) | 180 | struct gt215_clk_info *info) |
181 | { | 181 | { |
182 | struct gt215_clk_priv *priv = (void *)clock; | 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 | info->clk = 0; | 186 | info->clk = 0; |
186 | 187 | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c index c0fdb89e74ac..24dcdfb58a8d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c | |||
@@ -38,6 +38,14 @@ gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv) | |||
38 | nv_wr32(priv, 0x12004c, 0x4); | 38 | nv_wr32(priv, 0x12004c, 0x4); |
39 | nv_wr32(priv, 0x122204, 0x2); | 39 | nv_wr32(priv, 0x122204, 0x2); |
40 | nv_rd32(priv, 0x122204); | 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 | static void | 51 | static void |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c index 80614f1b2074..282143f49d72 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c | |||
@@ -50,7 +50,12 @@ nv04_instobj_dtor(struct nvkm_object *object) | |||
50 | { | 50 | { |
51 | struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object); | 51 | struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object); |
52 | struct nv04_instobj_priv *node = (void *)object; | 52 | struct nv04_instobj_priv *node = (void *)object; |
53 | struct nvkm_subdev *subdev = (void *)priv; | ||
54 | |||
55 | mutex_lock(&subdev->mutex); | ||
53 | nvkm_mm_free(&priv->heap, &node->mem); | 56 | nvkm_mm_free(&priv->heap, &node->mem); |
57 | mutex_unlock(&subdev->mutex); | ||
58 | |||
54 | nvkm_instobj_destroy(&node->base); | 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, | |||
62 | struct nv04_instmem_priv *priv = (void *)nvkm_instmem(parent); | 67 | struct nv04_instmem_priv *priv = (void *)nvkm_instmem(parent); |
63 | struct nv04_instobj_priv *node; | 68 | struct nv04_instobj_priv *node; |
64 | struct nvkm_instobj_args *args = data; | 69 | struct nvkm_instobj_args *args = data; |
70 | struct nvkm_subdev *subdev = (void *)priv; | ||
65 | int ret; | 71 | int ret; |
66 | 72 | ||
67 | if (!args->align) | 73 | if (!args->align) |
@@ -72,8 +78,10 @@ nv04_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, | |||
72 | if (ret) | 78 | if (ret) |
73 | return ret; | 79 | return ret; |
74 | 80 | ||
81 | mutex_lock(&subdev->mutex); | ||
75 | ret = nvkm_mm_head(&priv->heap, 0, 1, args->size, args->size, | 82 | ret = nvkm_mm_head(&priv->heap, 0, 1, args->size, args->size, |
76 | args->align, &node->mem); | 83 | args->align, &node->mem); |
84 | mutex_unlock(&subdev->mutex); | ||
77 | if (ret) | 85 | if (ret) |
78 | return ret; | 86 | return ret; |
79 | 87 | ||
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index dd39f434b4a7..c3872598b85a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |||
@@ -2299,8 +2299,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
2299 | encoder_mode = atombios_get_encoder_mode(encoder); | 2299 | encoder_mode = atombios_get_encoder_mode(encoder); |
2300 | if (connector && (radeon_audio != 0) && | 2300 | if (connector && (radeon_audio != 0) && |
2301 | ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || | 2301 | ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || |
2302 | (ENCODER_MODE_IS_DP(encoder_mode) && | 2302 | ENCODER_MODE_IS_DP(encoder_mode))) |
2303 | drm_detect_monitor_audio(radeon_connector_edid(connector))))) | ||
2304 | radeon_audio_mode_set(encoder, adjusted_mode); | 2303 | radeon_audio_mode_set(encoder, adjusted_mode); |
2305 | } | 2304 | } |
2306 | 2305 | ||
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 68fd9fc677e3..44480c1b9738 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c | |||
@@ -93,30 +93,26 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder) | |||
93 | struct radeon_device *rdev = encoder->dev->dev_private; | 93 | struct radeon_device *rdev = encoder->dev->dev_private; |
94 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 94 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
95 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 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 | return; | 98 | return; |
100 | 99 | ||
101 | offset = dig->afmt->offset; | 100 | WREG32(AFMT_AUDIO_SRC_CONTROL + dig->afmt->offset, |
102 | 101 | AFMT_AUDIO_SRC_SELECT(dig->pin->id)); | |
103 | WREG32(AFMT_AUDIO_SRC_CONTROL + offset, | ||
104 | AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id)); | ||
105 | } | 102 | } |
106 | 103 | ||
107 | void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, | 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 | struct radeon_device *rdev = encoder->dev->dev_private; | 108 | struct radeon_device *rdev = encoder->dev->dev_private; |
111 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 109 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
112 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 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 | return; | 114 | return; |
117 | 115 | ||
118 | offset = dig->afmt->pin->offset; | ||
119 | |||
120 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { | 116 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
121 | if (connector->latency_present[1]) | 117 | if (connector->latency_present[1]) |
122 | tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | | 118 | tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | |
@@ -130,24 +126,24 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, | |||
130 | else | 126 | else |
131 | tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0); | 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 | void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, | 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 | struct radeon_device *rdev = encoder->dev->dev_private; | 136 | struct radeon_device *rdev = encoder->dev->dev_private; |
140 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 137 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
141 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 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 | return; | 142 | return; |
146 | 143 | ||
147 | offset = dig->afmt->pin->offset; | ||
148 | |||
149 | /* program the speaker allocation */ | 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 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); | 147 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); |
152 | /* set HDMI mode */ | 148 | /* set HDMI mode */ |
153 | tmp |= HDMI_CONNECTION; | 149 | tmp |= HDMI_CONNECTION; |
@@ -155,24 +151,24 @@ void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, | |||
155 | tmp |= SPEAKER_ALLOCATION(sadb[0]); | 151 | tmp |= SPEAKER_ALLOCATION(sadb[0]); |
156 | else | 152 | else |
157 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | 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 | void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, | 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 | struct radeon_device *rdev = encoder->dev->dev_private; | 161 | struct radeon_device *rdev = encoder->dev->dev_private; |
165 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 162 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
166 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 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 | return; | 167 | return; |
171 | 168 | ||
172 | offset = dig->afmt->pin->offset; | ||
173 | |||
174 | /* program the speaker allocation */ | 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 | tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); | 172 | tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); |
177 | /* set DP mode */ | 173 | /* set DP mode */ |
178 | tmp |= DP_CONNECTION; | 174 | tmp |= DP_CONNECTION; |
@@ -180,13 +176,13 @@ void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, | |||
180 | tmp |= SPEAKER_ALLOCATION(sadb[0]); | 176 | tmp |= SPEAKER_ALLOCATION(sadb[0]); |
181 | else | 177 | else |
182 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | 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 | void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, | 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 | int i; | 186 | int i; |
191 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 187 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
192 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 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, | |||
206 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, | 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 | return; | 206 | return; |
211 | 207 | ||
212 | offset = dig->afmt->pin->offset; | ||
213 | |||
214 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { | 208 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { |
215 | u32 value = 0; | 209 | u32 value = 0; |
216 | u8 stereo_freqs = 0; | 210 | u8 stereo_freqs = 0; |
@@ -237,7 +231,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, | |||
237 | 231 | ||
238 | value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); | 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, | |||
253 | } | 247 | } |
254 | 248 | ||
255 | void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, | 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 | /* Two dtos; generally use dto0 for HDMI */ | 252 | /* Two dtos; generally use dto0 for HDMI */ |
259 | u32 value = 0; | 253 | u32 value = 0; |
@@ -272,7 +266,7 @@ void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, | |||
272 | } | 266 | } |
273 | 267 | ||
274 | void dce6_dp_audio_set_dto(struct radeon_device *rdev, | 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 | /* Two dtos; generally use dto1 for DP */ | 271 | /* Two dtos; generally use dto1 for DP */ |
278 | u32 value = 0; | 272 | u32 value = 0; |
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index fa719c53449b..fbc8d88d6e5d 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c | |||
@@ -245,6 +245,28 @@ static struct radeon_audio_funcs dce6_dp_funcs = { | |||
245 | static void radeon_audio_enable(struct radeon_device *rdev, | 245 | static void radeon_audio_enable(struct radeon_device *rdev, |
246 | struct r600_audio_pin *pin, u8 enable_mask) | 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 | if (rdev->audio.funcs->enable) | 270 | if (rdev->audio.funcs->enable) |
249 | rdev->audio.funcs->enable(rdev, pin, enable_mask); | 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, | |||
336 | 358 | ||
337 | static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) | 359 | static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) |
338 | { | 360 | { |
339 | struct radeon_encoder *radeon_encoder; | 361 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); |
340 | struct drm_connector *connector; | 362 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
341 | struct radeon_connector *radeon_connector = NULL; | ||
342 | struct cea_sad *sads; | 363 | struct cea_sad *sads; |
343 | int sad_count; | 364 | int sad_count; |
344 | 365 | ||
345 | list_for_each_entry(connector, | 366 | if (!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"); | ||
355 | return; | 367 | return; |
356 | } | ||
357 | 368 | ||
358 | sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads); | 369 | sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads); |
359 | if (sad_count <= 0) { | 370 | if (sad_count <= 0) { |
@@ -362,8 +373,6 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) | |||
362 | } | 373 | } |
363 | BUG_ON(!sads); | 374 | BUG_ON(!sads); |
364 | 375 | ||
365 | radeon_encoder = to_radeon_encoder(encoder); | ||
366 | |||
367 | if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs) | 376 | if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs) |
368 | radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count); | 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) | |||
372 | 381 | ||
373 | static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) | 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 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 385 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
376 | struct drm_connector *connector; | ||
377 | struct radeon_connector *radeon_connector = NULL; | ||
378 | u8 *sadb = NULL; | 386 | u8 *sadb = NULL; |
379 | int sad_count; | 387 | int sad_count; |
380 | 388 | ||
381 | list_for_each_entry(connector, | 389 | if (!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"); | ||
391 | return; | 390 | return; |
392 | } | ||
393 | 391 | ||
394 | sad_count = drm_edid_to_speaker_allocation( | 392 | sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), |
395 | radeon_connector_edid(connector), &sadb); | 393 | &sadb); |
396 | if (sad_count < 0) { | 394 | if (sad_count < 0) { |
397 | DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", | 395 | DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", |
398 | sad_count); | 396 | sad_count); |
@@ -406,26 +404,13 @@ static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) | |||
406 | } | 404 | } |
407 | 405 | ||
408 | static void radeon_audio_write_latency_fields(struct drm_encoder *encoder, | 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; | 409 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); |
412 | struct drm_connector *connector; | 410 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
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 | } | ||
422 | 411 | ||
423 | if (!radeon_connector) { | 412 | if (!connector) |
424 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
425 | return; | 413 | return; |
426 | } | ||
427 | |||
428 | radeon_encoder = to_radeon_encoder(encoder); | ||
429 | 414 | ||
430 | if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields) | 415 | if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields) |
431 | radeon_encoder->audio->write_latency_fields(encoder, connector, mode); | 416 | radeon_encoder->audio->write_latency_fields(encoder, connector, mode); |
@@ -451,29 +436,23 @@ static void radeon_audio_select_pin(struct drm_encoder *encoder) | |||
451 | } | 436 | } |
452 | 437 | ||
453 | void radeon_audio_detect(struct drm_connector *connector, | 438 | void radeon_audio_detect(struct drm_connector *connector, |
439 | struct drm_encoder *encoder, | ||
454 | enum drm_connector_status status) | 440 | enum drm_connector_status status) |
455 | { | 441 | { |
456 | struct radeon_device *rdev; | 442 | struct drm_device *dev = connector->dev; |
457 | struct radeon_encoder *radeon_encoder; | 443 | struct radeon_device *rdev = dev->dev_private; |
444 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
458 | struct radeon_encoder_atom_dig *dig; | 445 | struct radeon_encoder_atom_dig *dig; |
459 | 446 | ||
460 | if (!connector || !connector->encoder) | 447 | if (!radeon_audio_chipset_supported(rdev)) |
461 | return; | 448 | return; |
462 | 449 | ||
463 | rdev = connector->encoder->dev->dev_private; | 450 | if (!radeon_encoder_is_digital(encoder)) |
464 | |||
465 | if (!radeon_audio_chipset_supported(rdev)) | ||
466 | return; | 451 | return; |
467 | 452 | ||
468 | radeon_encoder = to_radeon_encoder(connector->encoder); | ||
469 | dig = radeon_encoder->enc_priv; | 453 | dig = radeon_encoder->enc_priv; |
470 | 454 | ||
471 | if (status == connector_status_connected) { | 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 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { | 456 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { |
478 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 457 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
479 | 458 | ||
@@ -486,11 +465,17 @@ void radeon_audio_detect(struct drm_connector *connector, | |||
486 | radeon_encoder->audio = rdev->audio.hdmi_funcs; | 465 | radeon_encoder->audio = rdev->audio.hdmi_funcs; |
487 | } | 466 | } |
488 | 467 | ||
489 | dig->afmt->pin = radeon_audio_get_pin(connector->encoder); | 468 | if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { |
490 | radeon_audio_enable(rdev, dig->afmt->pin, 0xf); | 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 | } else { | 476 | } else { |
492 | radeon_audio_enable(rdev, dig->afmt->pin, 0); | 477 | radeon_audio_enable(rdev, dig->pin, 0); |
493 | dig->afmt->pin = NULL; | 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 | |||
518 | } | 503 | } |
519 | 504 | ||
520 | static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, | 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 | struct radeon_device *rdev = encoder->dev->dev_private; | 508 | struct radeon_device *rdev = encoder->dev->dev_private; |
524 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 509 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
525 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 510 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
526 | struct drm_connector *connector; | 511 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); |
527 | struct radeon_connector *radeon_connector = NULL; | ||
528 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; | 512 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; |
529 | struct hdmi_avi_infoframe frame; | 513 | struct hdmi_avi_infoframe frame; |
530 | int err; | 514 | int err; |
531 | 515 | ||
532 | list_for_each_entry(connector, | 516 | if (!connector) |
533 | &encoder->dev->mode_config.connector_list, head) { | 517 | return -EINVAL; |
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 | } | ||
544 | 518 | ||
545 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); | 519 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); |
546 | if (err < 0) { | 520 | if (err < 0) { |
@@ -563,8 +537,8 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, | |||
563 | return err; | 537 | return err; |
564 | } | 538 | } |
565 | 539 | ||
566 | if (dig && dig->afmt && | 540 | if (dig && dig->afmt && radeon_encoder->audio && |
567 | radeon_encoder->audio && radeon_encoder->audio->set_avi_packet) | 541 | radeon_encoder->audio->set_avi_packet) |
568 | radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset, | 542 | radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset, |
569 | buffer, sizeof(buffer)); | 543 | buffer, sizeof(buffer)); |
570 | 544 | ||
@@ -722,30 +696,41 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, | |||
722 | { | 696 | { |
723 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 697 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
724 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 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 | if (!dig || !dig->afmt) | 701 | if (!dig || !dig->afmt) |
727 | return; | 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); | 707 | if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { |
732 | radeon_audio_write_sad_regs(encoder); | 708 | radeon_audio_set_mute(encoder, true); |
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); | ||
740 | 709 | ||
741 | if (radeon_audio_set_avi_packet(encoder, mode) < 0) | 710 | radeon_audio_write_speaker_allocation(encoder); |
742 | return; | 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 | static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, | 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 | struct drm_device *dev = encoder->dev; | 735 | struct drm_device *dev = encoder->dev; |
751 | struct radeon_device *rdev = dev->dev_private; | 736 | struct radeon_device *rdev = dev->dev_private; |
@@ -759,22 +744,27 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, | |||
759 | if (!dig || !dig->afmt) | 744 | if (!dig || !dig->afmt) |
760 | return; | 745 | return; |
761 | 746 | ||
762 | radeon_audio_write_speaker_allocation(encoder); | 747 | if (!connector) |
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) | ||
773 | return; | 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 | void radeon_audio_mode_set(struct drm_encoder *encoder, | 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 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 769 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
780 | 770 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h index 8438304f7139..059cc3012062 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.h +++ b/drivers/gpu/drm/radeon/radeon_audio.h | |||
@@ -68,7 +68,8 @@ struct radeon_audio_funcs | |||
68 | 68 | ||
69 | int radeon_audio_init(struct radeon_device *rdev); | 69 | int radeon_audio_init(struct radeon_device *rdev); |
70 | void radeon_audio_detect(struct drm_connector *connector, | 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 | u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, | 73 | u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, |
73 | u32 offset, u32 reg); | 74 | u32 offset, u32 reg); |
74 | void radeon_audio_endpoint_wreg(struct radeon_device *rdev, | 75 | void radeon_audio_endpoint_wreg(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 3e5f6b71f3ad..c097d3a82bda 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -1255,10 +1255,15 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder | |||
1255 | 1255 | ||
1256 | if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) && | 1256 | if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) && |
1257 | (RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) { | 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 | lvds->native_mode.htotal = lvds->native_mode.hdisplay + | 1263 | lvds->native_mode.htotal = lvds->native_mode.hdisplay + |
1259 | (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8; | 1264 | (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8; |
1260 | lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + | 1265 | lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + |
1261 | (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; | 1266 | hss; |
1262 | lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + | 1267 | lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + |
1263 | (RBIOS8(tmp + 23) * 8); | 1268 | (RBIOS8(tmp + 23) * 8); |
1264 | 1269 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index cebb65e07e1d..94b21ae70ef7 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -1379,8 +1379,16 @@ out: | |||
1379 | /* updated in get modes as well since we need to know if it's analog or digital */ | 1379 | /* updated in get modes as well since we need to know if it's analog or digital */ |
1380 | radeon_connector_update_scratch_regs(connector, ret); | 1380 | radeon_connector_update_scratch_regs(connector, ret); |
1381 | 1381 | ||
1382 | if (radeon_audio != 0) | 1382 | if ((radeon_audio != 0) && radeon_connector->use_digital) { |
1383 | radeon_audio_detect(connector, ret); | 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 | exit: | 1393 | exit: |
1386 | pm_runtime_mark_last_busy(connector->dev->dev); | 1394 | pm_runtime_mark_last_busy(connector->dev->dev); |
@@ -1717,8 +1725,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force) | |||
1717 | 1725 | ||
1718 | radeon_connector_update_scratch_regs(connector, ret); | 1726 | radeon_connector_update_scratch_regs(connector, ret); |
1719 | 1727 | ||
1720 | if (radeon_audio != 0) | 1728 | if ((radeon_audio != 0) && encoder) { |
1721 | radeon_audio_detect(connector, ret); | 1729 | radeon_connector_get_edid(connector); |
1730 | radeon_audio_detect(connector, encoder, ret); | ||
1731 | } | ||
1722 | 1732 | ||
1723 | out: | 1733 | out: |
1724 | pm_runtime_mark_last_busy(connector->dev->dev); | 1734 | pm_runtime_mark_last_busy(connector->dev->dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 07909d817381..aecc3e3dec0c 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -237,7 +237,6 @@ struct radeon_afmt { | |||
237 | int offset; | 237 | int offset; |
238 | bool last_buffer_filled_status; | 238 | bool last_buffer_filled_status; |
239 | int id; | 239 | int id; |
240 | struct r600_audio_pin *pin; | ||
241 | }; | 240 | }; |
242 | 241 | ||
243 | struct radeon_mode_info { | 242 | struct radeon_mode_info { |
@@ -439,6 +438,7 @@ struct radeon_encoder_atom_dig { | |||
439 | uint8_t backlight_level; | 438 | uint8_t backlight_level; |
440 | int panel_mode; | 439 | int panel_mode; |
441 | struct radeon_afmt *afmt; | 440 | struct radeon_afmt *afmt; |
441 | struct r600_audio_pin *pin; | ||
442 | int active_mst_links; | 442 | int active_mst_links; |
443 | }; | 443 | }; |
444 | 444 | ||
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index d708a53b8fb1..fbdd11851725 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h | |||
@@ -32,7 +32,7 @@ | |||
32 | #ifndef __AMDGPU_DRM_H__ | 32 | #ifndef __AMDGPU_DRM_H__ |
33 | #define __AMDGPU_DRM_H__ | 33 | #define __AMDGPU_DRM_H__ |
34 | 34 | ||
35 | #include <drm/drm.h> | 35 | #include "drm.h" |
36 | 36 | ||
37 | #define DRM_AMDGPU_GEM_CREATE 0x00 | 37 | #define DRM_AMDGPU_GEM_CREATE 0x00 |
38 | #define DRM_AMDGPU_GEM_MMAP 0x01 | 38 | #define DRM_AMDGPU_GEM_MMAP 0x01 |
diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h index 1ef76661e1a1..01aa2a8e3f8d 100644 --- a/include/uapi/drm/radeon_drm.h +++ b/include/uapi/drm/radeon_drm.h | |||
@@ -33,7 +33,7 @@ | |||
33 | #ifndef __RADEON_DRM_H__ | 33 | #ifndef __RADEON_DRM_H__ |
34 | #define __RADEON_DRM_H__ | 34 | #define __RADEON_DRM_H__ |
35 | 35 | ||
36 | #include <drm/drm.h> | 36 | #include "drm.h" |
37 | 37 | ||
38 | /* WARNING: If you change any of these defines, make sure to change the | 38 | /* WARNING: If you change any of these defines, make sure to change the |
39 | * defines in the X server file (radeon_sarea.h) | 39 | * defines in the X server file (radeon_sarea.h) |