diff options
75 files changed, 1355 insertions, 759 deletions
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 53b872c105d2..cb0d3537b705 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst | |||
| @@ -63,6 +63,9 @@ Frame Buffer Functions Reference | |||
| 63 | DRM Format Handling | 63 | DRM Format Handling |
| 64 | =================== | 64 | =================== |
| 65 | 65 | ||
| 66 | .. kernel-doc:: include/drm/drm_fourcc.h | ||
| 67 | :internal: | ||
| 68 | |||
| 66 | .. kernel-doc:: drivers/gpu/drm/drm_fourcc.c | 69 | .. kernel-doc:: drivers/gpu/drm/drm_fourcc.c |
| 67 | :export: | 70 | :export: |
| 68 | 71 | ||
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 1ba301cebe16..de3ac9f90f8f 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst | |||
| @@ -216,3 +216,9 @@ interfaces. Especially since all hardware-acceleration interfaces to | |||
| 216 | userspace are driver specific for efficiency and other reasons these | 216 | userspace are driver specific for efficiency and other reasons these |
| 217 | interfaces can be rather substantial. Hence every driver has its own | 217 | interfaces can be rather substantial. Hence every driver has its own |
| 218 | chapter. | 218 | chapter. |
| 219 | |||
| 220 | Testing and validation | ||
| 221 | ====================== | ||
| 222 | |||
| 223 | .. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c | ||
| 224 | :doc: CRC ABI | ||
diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 723d8af988e5..82de59f7cbbd 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c | |||
| @@ -280,18 +280,24 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, | |||
| 280 | unsigned *pshared_count, | 280 | unsigned *pshared_count, |
| 281 | struct fence ***pshared) | 281 | struct fence ***pshared) |
| 282 | { | 282 | { |
| 283 | unsigned shared_count = 0; | 283 | struct fence **shared = NULL; |
| 284 | unsigned retry = 1; | 284 | struct fence *fence_excl; |
| 285 | struct fence **shared = NULL, *fence_excl = NULL; | 285 | unsigned int shared_count; |
| 286 | int ret = 0; | 286 | int ret = 1; |
| 287 | 287 | ||
| 288 | while (retry) { | 288 | do { |
| 289 | struct reservation_object_list *fobj; | 289 | struct reservation_object_list *fobj; |
| 290 | unsigned seq; | 290 | unsigned seq; |
| 291 | unsigned int i; | ||
| 291 | 292 | ||
| 292 | seq = read_seqcount_begin(&obj->seq); | 293 | shared_count = i = 0; |
| 293 | 294 | ||
| 294 | rcu_read_lock(); | 295 | rcu_read_lock(); |
| 296 | seq = read_seqcount_begin(&obj->seq); | ||
| 297 | |||
| 298 | fence_excl = rcu_dereference(obj->fence_excl); | ||
| 299 | if (fence_excl && !fence_get_rcu(fence_excl)) | ||
| 300 | goto unlock; | ||
| 295 | 301 | ||
| 296 | fobj = rcu_dereference(obj->fence); | 302 | fobj = rcu_dereference(obj->fence); |
| 297 | if (fobj) { | 303 | if (fobj) { |
| @@ -309,52 +315,37 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, | |||
| 309 | } | 315 | } |
| 310 | 316 | ||
| 311 | ret = -ENOMEM; | 317 | ret = -ENOMEM; |
| 312 | shared_count = 0; | ||
| 313 | break; | 318 | break; |
| 314 | } | 319 | } |
| 315 | shared = nshared; | 320 | shared = nshared; |
| 316 | memcpy(shared, fobj->shared, sz); | ||
| 317 | shared_count = fobj->shared_count; | 321 | shared_count = fobj->shared_count; |
| 318 | } else | ||
| 319 | shared_count = 0; | ||
| 320 | fence_excl = rcu_dereference(obj->fence_excl); | ||
| 321 | |||
| 322 | retry = read_seqcount_retry(&obj->seq, seq); | ||
| 323 | if (retry) | ||
| 324 | goto unlock; | ||
| 325 | |||
| 326 | if (!fence_excl || fence_get_rcu(fence_excl)) { | ||
| 327 | unsigned i; | ||
| 328 | 322 | ||
| 329 | for (i = 0; i < shared_count; ++i) { | 323 | for (i = 0; i < shared_count; ++i) { |
| 330 | if (fence_get_rcu(shared[i])) | 324 | shared[i] = rcu_dereference(fobj->shared[i]); |
| 331 | continue; | 325 | if (!fence_get_rcu(shared[i])) |
| 332 | 326 | break; | |
| 333 | /* uh oh, refcount failed, abort and retry */ | ||
| 334 | while (i--) | ||
| 335 | fence_put(shared[i]); | ||
| 336 | |||
| 337 | if (fence_excl) { | ||
| 338 | fence_put(fence_excl); | ||
| 339 | fence_excl = NULL; | ||
| 340 | } | ||
| 341 | |||
| 342 | retry = 1; | ||
| 343 | break; | ||
| 344 | } | 327 | } |
| 345 | } else | 328 | } |
| 346 | retry = 1; | ||
| 347 | 329 | ||
| 330 | if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) { | ||
| 331 | while (i--) | ||
| 332 | fence_put(shared[i]); | ||
| 333 | fence_put(fence_excl); | ||
| 334 | goto unlock; | ||
| 335 | } | ||
| 336 | |||
| 337 | ret = 0; | ||
| 348 | unlock: | 338 | unlock: |
| 349 | rcu_read_unlock(); | 339 | rcu_read_unlock(); |
| 350 | } | 340 | } while (ret); |
| 351 | *pshared_count = shared_count; | 341 | |
| 352 | if (shared_count) | 342 | if (!shared_count) { |
| 353 | *pshared = shared; | ||
| 354 | else { | ||
| 355 | *pshared = NULL; | ||
| 356 | kfree(shared); | 343 | kfree(shared); |
| 344 | shared = NULL; | ||
| 357 | } | 345 | } |
| 346 | |||
| 347 | *pshared_count = shared_count; | ||
| 348 | *pshared = shared; | ||
| 358 | *pfence_excl = fence_excl; | 349 | *pfence_excl = fence_excl; |
| 359 | 350 | ||
| 360 | return ret; | 351 | return ret; |
| @@ -397,9 +388,6 @@ retry: | |||
| 397 | if (fobj) | 388 | if (fobj) |
| 398 | shared_count = fobj->shared_count; | 389 | shared_count = fobj->shared_count; |
| 399 | 390 | ||
| 400 | if (read_seqcount_retry(&obj->seq, seq)) | ||
| 401 | goto unlock_retry; | ||
| 402 | |||
| 403 | for (i = 0; i < shared_count; ++i) { | 391 | for (i = 0; i < shared_count; ++i) { |
| 404 | struct fence *lfence = rcu_dereference(fobj->shared[i]); | 392 | struct fence *lfence = rcu_dereference(fobj->shared[i]); |
| 405 | 393 | ||
| @@ -422,9 +410,6 @@ retry: | |||
| 422 | if (!shared_count) { | 410 | if (!shared_count) { |
| 423 | struct fence *fence_excl = rcu_dereference(obj->fence_excl); | 411 | struct fence *fence_excl = rcu_dereference(obj->fence_excl); |
| 424 | 412 | ||
| 425 | if (read_seqcount_retry(&obj->seq, seq)) | ||
| 426 | goto unlock_retry; | ||
| 427 | |||
| 428 | if (fence_excl && | 413 | if (fence_excl && |
| 429 | !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) { | 414 | !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) { |
| 430 | if (!fence_get_rcu(fence_excl)) | 415 | if (!fence_get_rcu(fence_excl)) |
| @@ -439,6 +424,11 @@ retry: | |||
| 439 | 424 | ||
| 440 | rcu_read_unlock(); | 425 | rcu_read_unlock(); |
| 441 | if (fence) { | 426 | if (fence) { |
| 427 | if (read_seqcount_retry(&obj->seq, seq)) { | ||
| 428 | fence_put(fence); | ||
| 429 | goto retry; | ||
| 430 | } | ||
| 431 | |||
| 442 | ret = fence_wait_timeout(fence, intr, ret); | 432 | ret = fence_wait_timeout(fence, intr, ret); |
| 443 | fence_put(fence); | 433 | fence_put(fence); |
| 444 | if (ret > 0 && wait_all && (i + 1 < shared_count)) | 434 | if (ret > 0 && wait_all && (i + 1 < shared_count)) |
| @@ -484,12 +474,13 @@ bool reservation_object_test_signaled_rcu(struct reservation_object *obj, | |||
| 484 | bool test_all) | 474 | bool test_all) |
| 485 | { | 475 | { |
| 486 | unsigned seq, shared_count; | 476 | unsigned seq, shared_count; |
| 487 | int ret = true; | 477 | int ret; |
| 488 | 478 | ||
| 479 | rcu_read_lock(); | ||
| 489 | retry: | 480 | retry: |
| 481 | ret = true; | ||
| 490 | shared_count = 0; | 482 | shared_count = 0; |
| 491 | seq = read_seqcount_begin(&obj->seq); | 483 | seq = read_seqcount_begin(&obj->seq); |
| 492 | rcu_read_lock(); | ||
| 493 | 484 | ||
| 494 | if (test_all) { | 485 | if (test_all) { |
| 495 | unsigned i; | 486 | unsigned i; |
| @@ -500,46 +491,35 @@ retry: | |||
| 500 | if (fobj) | 491 | if (fobj) |
| 501 | shared_count = fobj->shared_count; | 492 | shared_count = fobj->shared_count; |
| 502 | 493 | ||
| 503 | if (read_seqcount_retry(&obj->seq, seq)) | ||
| 504 | goto unlock_retry; | ||
| 505 | |||
| 506 | for (i = 0; i < shared_count; ++i) { | 494 | for (i = 0; i < shared_count; ++i) { |
| 507 | struct fence *fence = rcu_dereference(fobj->shared[i]); | 495 | struct fence *fence = rcu_dereference(fobj->shared[i]); |
| 508 | 496 | ||
| 509 | ret = reservation_object_test_signaled_single(fence); | 497 | ret = reservation_object_test_signaled_single(fence); |
| 510 | if (ret < 0) | 498 | if (ret < 0) |
| 511 | goto unlock_retry; | 499 | goto retry; |
| 512 | else if (!ret) | 500 | else if (!ret) |
| 513 | break; | 501 | break; |
| 514 | } | 502 | } |
| 515 | 503 | ||
| 516 | /* | 504 | if (read_seqcount_retry(&obj->seq, seq)) |
| 517 | * There could be a read_seqcount_retry here, but nothing cares | 505 | goto retry; |
| 518 | * about whether it's the old or newer fence pointers that are | ||
| 519 | * signaled. That race could still have happened after checking | ||
| 520 | * read_seqcount_retry. If you care, use ww_mutex_lock. | ||
| 521 | */ | ||
| 522 | } | 506 | } |
| 523 | 507 | ||
| 524 | if (!shared_count) { | 508 | if (!shared_count) { |
| 525 | struct fence *fence_excl = rcu_dereference(obj->fence_excl); | 509 | struct fence *fence_excl = rcu_dereference(obj->fence_excl); |
| 526 | 510 | ||
| 527 | if (read_seqcount_retry(&obj->seq, seq)) | ||
| 528 | goto unlock_retry; | ||
| 529 | |||
| 530 | if (fence_excl) { | 511 | if (fence_excl) { |
| 531 | ret = reservation_object_test_signaled_single( | 512 | ret = reservation_object_test_signaled_single( |
| 532 | fence_excl); | 513 | fence_excl); |
| 533 | if (ret < 0) | 514 | if (ret < 0) |
| 534 | goto unlock_retry; | 515 | goto retry; |
| 516 | |||
| 517 | if (read_seqcount_retry(&obj->seq, seq)) | ||
| 518 | goto retry; | ||
| 535 | } | 519 | } |
| 536 | } | 520 | } |
| 537 | 521 | ||
| 538 | rcu_read_unlock(); | 522 | rcu_read_unlock(); |
| 539 | return ret; | 523 | return ret; |
| 540 | |||
| 541 | unlock_retry: | ||
| 542 | rcu_read_unlock(); | ||
| 543 | goto retry; | ||
| 544 | } | 524 | } |
| 545 | EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu); | 525 | EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu); |
diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index b29a9e817320..235f8ac113cc 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c | |||
| @@ -79,7 +79,7 @@ struct sync_file *sync_file_create(struct fence *fence) | |||
| 79 | if (!sync_file) | 79 | if (!sync_file) |
| 80 | return NULL; | 80 | return NULL; |
| 81 | 81 | ||
| 82 | sync_file->fence = fence; | 82 | sync_file->fence = fence_get(fence); |
| 83 | 83 | ||
| 84 | snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d", | 84 | snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d", |
| 85 | fence->ops->get_driver_name(fence), | 85 | fence->ops->get_driver_name(fence), |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 25c720454017..74579d2e796e 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
| @@ -9,7 +9,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ | |||
| 9 | drm_scatter.o drm_pci.o \ | 9 | drm_scatter.o drm_pci.o \ |
| 10 | drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ | 10 | drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ |
| 11 | drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ | 11 | drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ |
| 12 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ | 12 | drm_info.o drm_encoder_slave.o \ |
| 13 | drm_trace_points.o drm_global.o drm_prime.o \ | 13 | drm_trace_points.o drm_global.o drm_prime.o \ |
| 14 | drm_rect.o drm_vma_manager.o drm_flip_work.o \ | 14 | drm_rect.o drm_vma_manager.o drm_flip_work.o \ |
| 15 | drm_modeset_lock.o drm_atomic.o drm_bridge.o \ | 15 | drm_modeset_lock.o drm_atomic.o drm_bridge.o \ |
| @@ -23,6 +23,7 @@ drm-$(CONFIG_PCI) += ati_pcigart.o | |||
| 23 | drm-$(CONFIG_DRM_PANEL) += drm_panel.o | 23 | drm-$(CONFIG_DRM_PANEL) += drm_panel.o |
| 24 | drm-$(CONFIG_OF) += drm_of.o | 24 | drm-$(CONFIG_OF) += drm_of.o |
| 25 | drm-$(CONFIG_AGP) += drm_agpsupport.o | 25 | drm-$(CONFIG_AGP) += drm_agpsupport.o |
| 26 | drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o | ||
| 26 | 27 | ||
| 27 | drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ | 28 | drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ |
| 28 | drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ | 29 | drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 9fb8aa4d6bae..8d01aa24d68a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | |||
| @@ -90,12 +90,12 @@ static struct fb_ops amdgpufb_ops = { | |||
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | 92 | ||
| 93 | int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tiled) | 93 | int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int cpp, bool tiled) |
| 94 | { | 94 | { |
| 95 | int aligned = width; | 95 | int aligned = width; |
| 96 | int pitch_mask = 0; | 96 | int pitch_mask = 0; |
| 97 | 97 | ||
| 98 | switch (bpp / 8) { | 98 | switch (cpp) { |
| 99 | case 1: | 99 | case 1: |
| 100 | pitch_mask = 255; | 100 | pitch_mask = 255; |
| 101 | break; | 101 | break; |
| @@ -110,7 +110,7 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile | |||
| 110 | 110 | ||
| 111 | aligned += pitch_mask; | 111 | aligned += pitch_mask; |
| 112 | aligned &= ~pitch_mask; | 112 | aligned &= ~pitch_mask; |
| 113 | return aligned; | 113 | return aligned * cpp; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj) | 116 | static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj) |
| @@ -139,13 +139,13 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, | |||
| 139 | int ret; | 139 | int ret; |
| 140 | int aligned_size, size; | 140 | int aligned_size, size; |
| 141 | int height = mode_cmd->height; | 141 | int height = mode_cmd->height; |
| 142 | u32 bpp, depth; | 142 | u32 cpp; |
| 143 | 143 | ||
| 144 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); | 144 | cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0); |
| 145 | 145 | ||
| 146 | /* need to align pitch with crtc limits */ | 146 | /* need to align pitch with crtc limits */ |
| 147 | mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, bpp, | 147 | mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp, |
| 148 | fb_tiled) * ((bpp + 1) / 8); | 148 | fb_tiled); |
| 149 | 149 | ||
| 150 | height = ALIGN(mode_cmd->height, 8); | 150 | height = ALIGN(mode_cmd->height, 8); |
| 151 | size = mode_cmd->pitches[0] * height; | 151 | size = mode_cmd->pitches[0] * height; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index a7ea9a3b454e..3ad0bf6ce3e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
| @@ -407,10 +407,8 @@ int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | |||
| 407 | return -ENOENT; | 407 | return -ENOENT; |
| 408 | } | 408 | } |
| 409 | robj = gem_to_amdgpu_bo(gobj); | 409 | robj = gem_to_amdgpu_bo(gobj); |
| 410 | if (timeout == 0) | 410 | ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, |
| 411 | ret = reservation_object_test_signaled_rcu(robj->tbo.resv, true); | 411 | timeout); |
| 412 | else | ||
| 413 | ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, timeout); | ||
| 414 | 412 | ||
| 415 | /* ret == 0 means not signaled, | 413 | /* ret == 0 means not signaled, |
| 416 | * ret > 0 means signaled | 414 | * ret > 0 means signaled |
| @@ -704,7 +702,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, | |||
| 704 | uint32_t handle; | 702 | uint32_t handle; |
| 705 | int r; | 703 | int r; |
| 706 | 704 | ||
| 707 | args->pitch = amdgpu_align_pitch(adev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); | 705 | args->pitch = amdgpu_align_pitch(adev, args->width, |
| 706 | DIV_ROUND_UP(args->bpp, 8), 0); | ||
| 708 | args->size = (u64)args->pitch * args->height; | 707 | args->size = (u64)args->pitch * args->height; |
| 709 | args->size = ALIGN(args->size, PAGE_SIZE); | 708 | args->size = ALIGN(args->size, PAGE_SIZE); |
| 710 | 709 | ||
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 48019ae22ddb..bbaa55add2d2 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c | |||
| @@ -223,14 +223,12 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, | |||
| 223 | { | 223 | { |
| 224 | struct hdlcd_drm_private *hdlcd; | 224 | struct hdlcd_drm_private *hdlcd; |
| 225 | struct drm_gem_cma_object *gem; | 225 | struct drm_gem_cma_object *gem; |
| 226 | unsigned int depth, bpp; | ||
| 227 | u32 src_w, src_h, dest_w, dest_h; | 226 | u32 src_w, src_h, dest_w, dest_h; |
| 228 | dma_addr_t scanout_start; | 227 | dma_addr_t scanout_start; |
| 229 | 228 | ||
| 230 | if (!plane->state->fb) | 229 | if (!plane->state->fb) |
| 231 | return; | 230 | return; |
| 232 | 231 | ||
| 233 | drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp); | ||
| 234 | src_w = plane->state->src_w >> 16; | 232 | src_w = plane->state->src_w >> 16; |
| 235 | src_h = plane->state->src_h >> 16; | 233 | src_h = plane->state->src_h >> 16; |
| 236 | dest_w = plane->state->crtc_w; | 234 | dest_w = plane->state->crtc_w; |
| @@ -238,7 +236,8 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, | |||
| 238 | gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); | 236 | gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); |
| 239 | scanout_start = gem->paddr + plane->state->fb->offsets[0] + | 237 | scanout_start = gem->paddr + plane->state->fb->offsets[0] + |
| 240 | plane->state->crtc_y * plane->state->fb->pitches[0] + | 238 | plane->state->crtc_y * plane->state->fb->pitches[0] + |
| 241 | plane->state->crtc_x * bpp / 8; | 239 | plane->state->crtc_x * |
| 240 | drm_format_plane_cpp(plane->state->fb->pixel_format, 0); | ||
| 242 | 241 | ||
| 243 | hdlcd = plane->dev->dev_private; | 242 | hdlcd = plane->dev->dev_private; |
| 244 | hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]); | 243 | hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]); |
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index a6132f1d58c1..be815d0cc772 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c | |||
| @@ -198,9 +198,6 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode * | |||
| 198 | 198 | ||
| 199 | static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt) | 199 | static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt) |
| 200 | { | 200 | { |
| 201 | unsigned int depth; | ||
| 202 | int bpp; | ||
| 203 | |||
| 204 | /* RGB888 or BGR888 can't be rotated */ | 201 | /* RGB888 or BGR888 can't be rotated */ |
| 205 | if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888)) | 202 | if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888)) |
| 206 | return -EINVAL; | 203 | return -EINVAL; |
| @@ -210,9 +207,7 @@ static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 | |||
| 210 | * worth of pixel data. Required size is then: | 207 | * worth of pixel data. Required size is then: |
| 211 | * size = rotated_width * (bpp / 8) * 8; | 208 | * size = rotated_width * (bpp / 8) * 8; |
| 212 | */ | 209 | */ |
| 213 | drm_fb_get_bpp_depth(fmt, &depth, &bpp); | 210 | return w * drm_format_plane_cpp(fmt, 0) * 8; |
| 214 | |||
| 215 | return w * bpp; | ||
| 216 | } | 211 | } |
| 217 | 212 | ||
| 218 | static int malidp550_query_hw(struct malidp_hw_device *hwdev) | 213 | static int malidp550_query_hw(struct malidp_hw_device *hwdev) |
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 82c193e5e0d6..abaca03b9d36 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c | |||
| @@ -254,21 +254,18 @@ int malidp_de_planes_init(struct drm_device *drm) | |||
| 254 | if (ret < 0) | 254 | if (ret < 0) |
| 255 | goto cleanup; | 255 | goto cleanup; |
| 256 | 256 | ||
| 257 | if (!drm->mode_config.rotation_property) { | 257 | /* SMART layer can't be rotated */ |
| 258 | if (id != DE_SMART) { | ||
| 258 | unsigned long flags = DRM_ROTATE_0 | | 259 | unsigned long flags = DRM_ROTATE_0 | |
| 259 | DRM_ROTATE_90 | | 260 | DRM_ROTATE_90 | |
| 260 | DRM_ROTATE_180 | | 261 | DRM_ROTATE_180 | |
| 261 | DRM_ROTATE_270 | | 262 | DRM_ROTATE_270 | |
| 262 | DRM_REFLECT_X | | 263 | DRM_REFLECT_X | |
| 263 | DRM_REFLECT_Y; | 264 | DRM_REFLECT_Y; |
| 264 | drm->mode_config.rotation_property = | 265 | drm_plane_create_rotation_property(&plane->base, |
| 265 | drm_mode_create_rotation_property(drm, flags); | 266 | DRM_ROTATE_0, |
| 267 | flags); | ||
| 266 | } | 268 | } |
| 267 | /* SMART layer can't be rotated */ | ||
| 268 | if (drm->mode_config.rotation_property && (id != DE_SMART)) | ||
| 269 | drm_object_attach_property(&plane->base.base, | ||
| 270 | drm->mode_config.rotation_property, | ||
| 271 | DRM_ROTATE_0); | ||
| 272 | 269 | ||
| 273 | drm_plane_helper_add(&plane->base, | 270 | drm_plane_helper_add(&plane->base, |
| 274 | &malidp_de_plane_helper_funcs); | 271 | &malidp_de_plane_helper_funcs); |
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 5f484310bee9..9f6222895212 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | |||
| @@ -464,7 +464,7 @@ atmel_hlcdc_dc_atomic_complete(struct atmel_hlcdc_dc_commit *commit) | |||
| 464 | 464 | ||
| 465 | drm_atomic_helper_cleanup_planes(dev, old_state); | 465 | drm_atomic_helper_cleanup_planes(dev, old_state); |
| 466 | 466 | ||
| 467 | drm_atomic_state_free(old_state); | 467 | drm_atomic_state_put(old_state); |
| 468 | 468 | ||
| 469 | /* Complete the commit, wake up any waiter. */ | 469 | /* Complete the commit, wake up any waiter. */ |
| 470 | spin_lock(&dc->commit.wait.lock); | 470 | spin_lock(&dc->commit.wait.lock); |
| @@ -521,6 +521,7 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev, | |||
| 521 | /* Swap the state, this is the point of no return. */ | 521 | /* Swap the state, this is the point of no return. */ |
| 522 | drm_atomic_helper_swap_state(state, true); | 522 | drm_atomic_helper_swap_state(state, true); |
| 523 | 523 | ||
| 524 | drm_atomic_state_get(state); | ||
| 524 | if (async) | 525 | if (async) |
| 525 | queue_work(dc->wq, &commit->work); | 526 | queue_work(dc->wq, &commit->work); |
| 526 | else | 527 | else |
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 9d4c030672f0..246ed1e33d8a 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | |||
| @@ -393,7 +393,7 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, | |||
| 393 | 393 | ||
| 394 | if ((state->base.fb->pixel_format == DRM_FORMAT_YUV422 || | 394 | if ((state->base.fb->pixel_format == DRM_FORMAT_YUV422 || |
| 395 | state->base.fb->pixel_format == DRM_FORMAT_NV61) && | 395 | state->base.fb->pixel_format == DRM_FORMAT_NV61) && |
| 396 | (state->base.rotation & (DRM_ROTATE_90 | DRM_ROTATE_270))) | 396 | drm_rotation_90_or_270(state->base.rotation)) |
| 397 | cfg |= ATMEL_HLCDC_YUV422ROT; | 397 | cfg |= ATMEL_HLCDC_YUV422ROT; |
| 398 | 398 | ||
| 399 | atmel_hlcdc_layer_update_cfg(&plane->layer, | 399 | atmel_hlcdc_layer_update_cfg(&plane->layer, |
| @@ -628,7 +628,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, | |||
| 628 | /* | 628 | /* |
| 629 | * Swap width and size in case of 90 or 270 degrees rotation | 629 | * Swap width and size in case of 90 or 270 degrees rotation |
| 630 | */ | 630 | */ |
| 631 | if (state->base.rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)) { | 631 | if (drm_rotation_90_or_270(state->base.rotation)) { |
| 632 | tmp = state->crtc_w; | 632 | tmp = state->crtc_w; |
| 633 | state->crtc_w = state->crtc_h; | 633 | state->crtc_w = state->crtc_h; |
| 634 | state->crtc_h = tmp; | 634 | state->crtc_h = tmp; |
| @@ -883,9 +883,9 @@ static int atmel_hlcdc_plane_atomic_get_property(struct drm_plane *p, | |||
| 883 | return 0; | 883 | return 0; |
| 884 | } | 884 | } |
| 885 | 885 | ||
| 886 | static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, | 886 | static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, |
| 887 | const struct atmel_hlcdc_layer_desc *desc, | 887 | const struct atmel_hlcdc_layer_desc *desc, |
| 888 | struct atmel_hlcdc_plane_properties *props) | 888 | struct atmel_hlcdc_plane_properties *props) |
| 889 | { | 889 | { |
| 890 | struct regmap *regmap = plane->layer.hlcdc->regmap; | 890 | struct regmap *regmap = plane->layer.hlcdc->regmap; |
| 891 | 891 | ||
| @@ -902,10 +902,18 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, | |||
| 902 | ATMEL_HLCDC_LAYER_GA_MASK); | 902 | ATMEL_HLCDC_LAYER_GA_MASK); |
| 903 | } | 903 | } |
| 904 | 904 | ||
| 905 | if (desc->layout.xstride && desc->layout.pstride) | 905 | if (desc->layout.xstride && desc->layout.pstride) { |
| 906 | drm_object_attach_property(&plane->base.base, | 906 | int ret; |
| 907 | plane->base.dev->mode_config.rotation_property, | 907 | |
| 908 | DRM_ROTATE_0); | 908 | ret = drm_plane_create_rotation_property(&plane->base, |
| 909 | DRM_ROTATE_0, | ||
| 910 | DRM_ROTATE_0 | | ||
| 911 | DRM_ROTATE_90 | | ||
| 912 | DRM_ROTATE_180 | | ||
| 913 | DRM_ROTATE_270); | ||
| 914 | if (ret) | ||
| 915 | return ret; | ||
| 916 | } | ||
| 909 | 917 | ||
| 910 | if (desc->layout.csc) { | 918 | if (desc->layout.csc) { |
| 911 | /* | 919 | /* |
| @@ -925,6 +933,8 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, | |||
| 925 | ATMEL_HLCDC_LAYER_CSC_CFG(&plane->layer, 2), | 933 | ATMEL_HLCDC_LAYER_CSC_CFG(&plane->layer, 2), |
| 926 | 0x40040890); | 934 | 0x40040890); |
| 927 | } | 935 | } |
| 936 | |||
| 937 | return 0; | ||
| 928 | } | 938 | } |
| 929 | 939 | ||
| 930 | static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { | 940 | static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { |
| @@ -1036,7 +1046,9 @@ atmel_hlcdc_plane_create(struct drm_device *dev, | |||
| 1036 | &atmel_hlcdc_layer_plane_helper_funcs); | 1046 | &atmel_hlcdc_layer_plane_helper_funcs); |
| 1037 | 1047 | ||
| 1038 | /* Set default property values*/ | 1048 | /* Set default property values*/ |
| 1039 | atmel_hlcdc_plane_init_properties(plane, desc, props); | 1049 | ret = atmel_hlcdc_plane_init_properties(plane, desc, props); |
| 1050 | if (ret) | ||
| 1051 | return ERR_PTR(ret); | ||
| 1040 | 1052 | ||
| 1041 | return plane; | 1053 | return plane; |
| 1042 | } | 1054 | } |
| @@ -1054,15 +1066,6 @@ atmel_hlcdc_plane_create_properties(struct drm_device *dev) | |||
| 1054 | if (!props->alpha) | 1066 | if (!props->alpha) |
| 1055 | return ERR_PTR(-ENOMEM); | 1067 | return ERR_PTR(-ENOMEM); |
| 1056 | 1068 | ||
| 1057 | dev->mode_config.rotation_property = | ||
| 1058 | drm_mode_create_rotation_property(dev, | ||
| 1059 | DRM_ROTATE_0 | | ||
| 1060 | DRM_ROTATE_90 | | ||
| 1061 | DRM_ROTATE_180 | | ||
| 1062 | DRM_ROTATE_270); | ||
| 1063 | if (!dev->mode_config.rotation_property) | ||
| 1064 | return ERR_PTR(-ENOMEM); | ||
| 1065 | |||
| 1066 | return props; | 1069 | return props; |
| 1067 | } | 1070 | } |
| 1068 | 1071 | ||
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index daecf1ad76a4..3a6309d7d8e4 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c | |||
| @@ -138,12 +138,12 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev, | |||
| 138 | { | 138 | { |
| 139 | struct drm_device *dev = afbdev->helper.dev; | 139 | struct drm_device *dev = afbdev->helper.dev; |
| 140 | struct cirrus_device *cdev = dev->dev_private; | 140 | struct cirrus_device *cdev = dev->dev_private; |
| 141 | u32 bpp, depth; | 141 | u32 bpp; |
| 142 | u32 size; | 142 | u32 size; |
| 143 | struct drm_gem_object *gobj; | 143 | struct drm_gem_object *gobj; |
| 144 | |||
| 145 | int ret = 0; | 144 | int ret = 0; |
| 146 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); | 145 | |
| 146 | bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8; | ||
| 147 | 147 | ||
| 148 | if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, | 148 | if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, |
| 149 | bpp, mode_cmd->pitches[0])) | 149 | bpp, mode_cmd->pitches[0])) |
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index 76bcb43e7c06..2c3c0d4072ce 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c | |||
| @@ -52,10 +52,10 @@ cirrus_user_framebuffer_create(struct drm_device *dev, | |||
| 52 | struct cirrus_device *cdev = dev->dev_private; | 52 | struct cirrus_device *cdev = dev->dev_private; |
| 53 | struct drm_gem_object *obj; | 53 | struct drm_gem_object *obj; |
| 54 | struct cirrus_framebuffer *cirrus_fb; | 54 | struct cirrus_framebuffer *cirrus_fb; |
| 55 | u32 bpp; | ||
| 55 | int ret; | 56 | int ret; |
| 56 | u32 bpp, depth; | ||
| 57 | 57 | ||
| 58 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); | 58 | bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8; |
| 59 | 59 | ||
| 60 | if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, | 60 | if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, |
| 61 | bpp, mode_cmd->pitches[0])) | 61 | bpp, mode_cmd->pitches[0])) |
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 23739609427d..f81706387889 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
| @@ -74,6 +74,8 @@ EXPORT_SYMBOL(drm_atomic_state_default_release); | |||
| 74 | int | 74 | int |
| 75 | drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) | 75 | drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) |
| 76 | { | 76 | { |
| 77 | kref_init(&state->ref); | ||
| 78 | |||
| 77 | /* TODO legacy paths should maybe do a better job about | 79 | /* TODO legacy paths should maybe do a better job about |
| 78 | * setting this appropriately? | 80 | * setting this appropriately? |
| 79 | */ | 81 | */ |
| @@ -215,22 +217,16 @@ void drm_atomic_state_clear(struct drm_atomic_state *state) | |||
| 215 | EXPORT_SYMBOL(drm_atomic_state_clear); | 217 | EXPORT_SYMBOL(drm_atomic_state_clear); |
| 216 | 218 | ||
| 217 | /** | 219 | /** |
| 218 | * drm_atomic_state_free - free all memory for an atomic state | 220 | * __drm_atomic_state_free - free all memory for an atomic state |
| 219 | * @state: atomic state to deallocate | 221 | * @ref: This atomic state to deallocate |
| 220 | * | 222 | * |
| 221 | * This frees all memory associated with an atomic state, including all the | 223 | * This frees all memory associated with an atomic state, including all the |
| 222 | * per-object state for planes, crtcs and connectors. | 224 | * per-object state for planes, crtcs and connectors. |
| 223 | */ | 225 | */ |
| 224 | void drm_atomic_state_free(struct drm_atomic_state *state) | 226 | void __drm_atomic_state_free(struct kref *ref) |
| 225 | { | 227 | { |
| 226 | struct drm_device *dev; | 228 | struct drm_atomic_state *state = container_of(ref, typeof(*state), ref); |
| 227 | struct drm_mode_config *config; | 229 | struct drm_mode_config *config = &state->dev->mode_config; |
| 228 | |||
| 229 | if (!state) | ||
| 230 | return; | ||
| 231 | |||
| 232 | dev = state->dev; | ||
| 233 | config = &dev->mode_config; | ||
| 234 | 230 | ||
| 235 | drm_atomic_state_clear(state); | 231 | drm_atomic_state_clear(state); |
| 236 | 232 | ||
| @@ -243,7 +239,7 @@ void drm_atomic_state_free(struct drm_atomic_state *state) | |||
| 243 | kfree(state); | 239 | kfree(state); |
| 244 | } | 240 | } |
| 245 | } | 241 | } |
| 246 | EXPORT_SYMBOL(drm_atomic_state_free); | 242 | EXPORT_SYMBOL(__drm_atomic_state_free); |
| 247 | 243 | ||
| 248 | /** | 244 | /** |
| 249 | * drm_atomic_get_crtc_state - get crtc state | 245 | * drm_atomic_get_crtc_state - get crtc state |
| @@ -709,7 +705,10 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, | |||
| 709 | state->src_w = val; | 705 | state->src_w = val; |
| 710 | } else if (property == config->prop_src_h) { | 706 | } else if (property == config->prop_src_h) { |
| 711 | state->src_h = val; | 707 | state->src_h = val; |
| 712 | } else if (property == config->rotation_property) { | 708 | } else if (property == config->rotation_property || |
| 709 | property == plane->rotation_property) { | ||
| 710 | if (!is_power_of_2(val & DRM_ROTATE_MASK)) | ||
| 711 | return -EINVAL; | ||
| 713 | state->rotation = val; | 712 | state->rotation = val; |
| 714 | } else if (property == plane->zpos_property) { | 713 | } else if (property == plane->zpos_property) { |
| 715 | state->zpos = val; | 714 | state->zpos = val; |
| @@ -767,7 +766,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, | |||
| 767 | *val = state->src_w; | 766 | *val = state->src_w; |
| 768 | } else if (property == config->prop_src_h) { | 767 | } else if (property == config->prop_src_h) { |
| 769 | *val = state->src_h; | 768 | *val = state->src_h; |
| 770 | } else if (property == config->rotation_property) { | 769 | } else if (property == config->rotation_property || |
| 770 | property == plane->rotation_property) { | ||
| 771 | *val = state->rotation; | 771 | *val = state->rotation; |
| 772 | } else if (property == plane->zpos_property) { | 772 | } else if (property == plane->zpos_property) { |
| 773 | *val = state->zpos; | 773 | *val = state->zpos; |
| @@ -1742,7 +1742,7 @@ retry: | |||
| 1742 | if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { | 1742 | if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { |
| 1743 | /* | 1743 | /* |
| 1744 | * Unlike commit, check_only does not clean up state. | 1744 | * Unlike commit, check_only does not clean up state. |
| 1745 | * Below we call drm_atomic_state_free for it. | 1745 | * Below we call drm_atomic_state_put for it. |
| 1746 | */ | 1746 | */ |
| 1747 | ret = drm_atomic_check_only(state); | 1747 | ret = drm_atomic_check_only(state); |
| 1748 | } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { | 1748 | } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { |
| @@ -1775,8 +1775,7 @@ out: | |||
| 1775 | goto retry; | 1775 | goto retry; |
| 1776 | } | 1776 | } |
| 1777 | 1777 | ||
| 1778 | if (ret || arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) | 1778 | drm_atomic_state_put(state); |
| 1779 | drm_atomic_state_free(state); | ||
| 1780 | 1779 | ||
| 1781 | drm_modeset_drop_locks(&ctx); | 1780 | drm_modeset_drop_locks(&ctx); |
| 1782 | drm_modeset_acquire_fini(&ctx); | 1781 | drm_modeset_acquire_fini(&ctx); |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index c3f83476f996..f9362760bfb2 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
| @@ -458,10 +458,11 @@ mode_fixup(struct drm_atomic_state *state) | |||
| 458 | * removed from the crtc. | 458 | * removed from the crtc. |
| 459 | * crtc_state->active_changed is set when crtc_state->active changes, | 459 | * crtc_state->active_changed is set when crtc_state->active changes, |
| 460 | * which is used for dpms. | 460 | * which is used for dpms. |
| 461 | * See also: drm_atomic_crtc_needs_modeset() | ||
| 461 | * | 462 | * |
| 462 | * IMPORTANT: | 463 | * IMPORTANT: |
| 463 | * | 464 | * |
| 464 | * Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a | 465 | * Drivers which set ->mode_changed (e.g. in their ->atomic_check hooks if a |
| 465 | * plane update can't be done without a full modeset) _must_ call this function | 466 | * plane update can't be done without a full modeset) _must_ call this function |
| 466 | * afterwards after that change. It is permitted to call this function multiple | 467 | * afterwards after that change. It is permitted to call this function multiple |
| 467 | * times for the same update, e.g. when the ->atomic_check functions depend upon | 468 | * times for the same update, e.g. when the ->atomic_check functions depend upon |
| @@ -510,9 +511,9 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, | |||
| 510 | 511 | ||
| 511 | for_each_connector_in_state(state, connector, connector_state, i) { | 512 | for_each_connector_in_state(state, connector, connector_state, i) { |
| 512 | /* | 513 | /* |
| 513 | * This only sets crtc->mode_changed for routing changes, | 514 | * This only sets crtc->connectors_changed for routing changes, |
| 514 | * drivers must set crtc->mode_changed themselves when connector | 515 | * drivers must set crtc->connectors_changed themselves when |
| 515 | * properties need to be updated. | 516 | * connector properties need to be updated. |
| 516 | */ | 517 | */ |
| 517 | ret = update_connector_routing(state, connector, | 518 | ret = update_connector_routing(state, connector, |
| 518 | connector_state); | 519 | connector_state); |
| @@ -1207,7 +1208,7 @@ static void commit_tail(struct drm_atomic_state *state) | |||
| 1207 | 1208 | ||
| 1208 | drm_atomic_helper_commit_cleanup_done(state); | 1209 | drm_atomic_helper_commit_cleanup_done(state); |
| 1209 | 1210 | ||
| 1210 | drm_atomic_state_free(state); | 1211 | drm_atomic_state_put(state); |
| 1211 | } | 1212 | } |
| 1212 | 1213 | ||
| 1213 | static void commit_work(struct work_struct *work) | 1214 | static void commit_work(struct work_struct *work) |
| @@ -1289,6 +1290,7 @@ int drm_atomic_helper_commit(struct drm_device *dev, | |||
| 1289 | * make sure work items don't artifically stall on each another. | 1290 | * make sure work items don't artifically stall on each another. |
| 1290 | */ | 1291 | */ |
| 1291 | 1292 | ||
| 1293 | drm_atomic_state_get(state); | ||
| 1292 | if (nonblock) | 1294 | if (nonblock) |
| 1293 | queue_work(system_unbound_wq, &state->commit_work); | 1295 | queue_work(system_unbound_wq, &state->commit_work); |
| 1294 | else | 1296 | else |
| @@ -1590,7 +1592,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); | |||
| 1590 | * | 1592 | * |
| 1591 | * This signals completion of the atomic update @state, including any cleanup | 1593 | * This signals completion of the atomic update @state, including any cleanup |
| 1592 | * work. If used, it must be called right before calling | 1594 | * work. If used, it must be called right before calling |
| 1593 | * drm_atomic_state_free(). | 1595 | * drm_atomic_state_put(). |
| 1594 | * | 1596 | * |
| 1595 | * This is part of the atomic helper support for nonblocking commits, see | 1597 | * This is part of the atomic helper support for nonblocking commits, see |
| 1596 | * drm_atomic_helper_setup_commit() for an overview. | 1598 | * drm_atomic_helper_setup_commit() for an overview. |
| @@ -2113,18 +2115,13 @@ retry: | |||
| 2113 | state->legacy_cursor_update = true; | 2115 | state->legacy_cursor_update = true; |
| 2114 | 2116 | ||
| 2115 | ret = drm_atomic_commit(state); | 2117 | ret = drm_atomic_commit(state); |
| 2116 | if (ret != 0) | ||
| 2117 | goto fail; | ||
| 2118 | |||
| 2119 | /* Driver takes ownership of state on successful commit. */ | ||
| 2120 | return 0; | ||
| 2121 | fail: | 2118 | fail: |
| 2122 | if (ret == -EDEADLK) | 2119 | if (ret == -EDEADLK) |
| 2123 | goto backoff; | 2120 | goto backoff; |
| 2124 | 2121 | ||
| 2125 | drm_atomic_state_free(state); | 2122 | drm_atomic_state_put(state); |
| 2126 | |||
| 2127 | return ret; | 2123 | return ret; |
| 2124 | |||
| 2128 | backoff: | 2125 | backoff: |
| 2129 | drm_atomic_state_clear(state); | 2126 | drm_atomic_state_clear(state); |
| 2130 | drm_atomic_legacy_backoff(state); | 2127 | drm_atomic_legacy_backoff(state); |
| @@ -2186,18 +2183,13 @@ retry: | |||
| 2186 | goto fail; | 2183 | goto fail; |
| 2187 | 2184 | ||
| 2188 | ret = drm_atomic_commit(state); | 2185 | ret = drm_atomic_commit(state); |
| 2189 | if (ret != 0) | ||
| 2190 | goto fail; | ||
| 2191 | |||
| 2192 | /* Driver takes ownership of state on successful commit. */ | ||
| 2193 | return 0; | ||
| 2194 | fail: | 2186 | fail: |
| 2195 | if (ret == -EDEADLK) | 2187 | if (ret == -EDEADLK) |
| 2196 | goto backoff; | 2188 | goto backoff; |
| 2197 | 2189 | ||
| 2198 | drm_atomic_state_free(state); | 2190 | drm_atomic_state_put(state); |
| 2199 | |||
| 2200 | return ret; | 2191 | return ret; |
| 2192 | |||
| 2201 | backoff: | 2193 | backoff: |
| 2202 | drm_atomic_state_clear(state); | 2194 | drm_atomic_state_clear(state); |
| 2203 | drm_atomic_legacy_backoff(state); | 2195 | drm_atomic_legacy_backoff(state); |
| @@ -2326,18 +2318,13 @@ retry: | |||
| 2326 | goto fail; | 2318 | goto fail; |
| 2327 | 2319 | ||
| 2328 | ret = drm_atomic_commit(state); | 2320 | ret = drm_atomic_commit(state); |
| 2329 | if (ret != 0) | ||
| 2330 | goto fail; | ||
| 2331 | |||
| 2332 | /* Driver takes ownership of state on successful commit. */ | ||
| 2333 | return 0; | ||
| 2334 | fail: | 2321 | fail: |
| 2335 | if (ret == -EDEADLK) | 2322 | if (ret == -EDEADLK) |
| 2336 | goto backoff; | 2323 | goto backoff; |
| 2337 | 2324 | ||
| 2338 | drm_atomic_state_free(state); | 2325 | drm_atomic_state_put(state); |
| 2339 | |||
| 2340 | return ret; | 2326 | return ret; |
| 2327 | |||
| 2341 | backoff: | 2328 | backoff: |
| 2342 | drm_atomic_state_clear(state); | 2329 | drm_atomic_state_clear(state); |
| 2343 | drm_atomic_legacy_backoff(state); | 2330 | drm_atomic_legacy_backoff(state); |
| @@ -2412,7 +2399,7 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, | |||
| 2412 | primary_state->crtc_h = vdisplay; | 2399 | primary_state->crtc_h = vdisplay; |
| 2413 | primary_state->src_x = set->x << 16; | 2400 | primary_state->src_x = set->x << 16; |
| 2414 | primary_state->src_y = set->y << 16; | 2401 | primary_state->src_y = set->y << 16; |
| 2415 | if (primary_state->rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)) { | 2402 | if (drm_rotation_90_or_270(primary_state->rotation)) { |
| 2416 | primary_state->src_w = vdisplay << 16; | 2403 | primary_state->src_w = vdisplay << 16; |
| 2417 | primary_state->src_h = hdisplay << 16; | 2404 | primary_state->src_h = hdisplay << 16; |
| 2418 | } else { | 2405 | } else { |
| @@ -2479,11 +2466,8 @@ int drm_atomic_helper_disable_all(struct drm_device *dev, | |||
| 2479 | } | 2466 | } |
| 2480 | 2467 | ||
| 2481 | err = drm_atomic_commit(state); | 2468 | err = drm_atomic_commit(state); |
| 2482 | |||
| 2483 | free: | 2469 | free: |
| 2484 | if (err < 0) | 2470 | drm_atomic_state_put(state); |
| 2485 | drm_atomic_state_free(state); | ||
| 2486 | |||
| 2487 | return err; | 2471 | return err; |
| 2488 | } | 2472 | } |
| 2489 | EXPORT_SYMBOL(drm_atomic_helper_disable_all); | 2473 | EXPORT_SYMBOL(drm_atomic_helper_disable_all); |
| @@ -2534,7 +2518,7 @@ retry: | |||
| 2534 | 2518 | ||
| 2535 | err = drm_atomic_helper_disable_all(dev, &ctx); | 2519 | err = drm_atomic_helper_disable_all(dev, &ctx); |
| 2536 | if (err < 0) { | 2520 | if (err < 0) { |
| 2537 | drm_atomic_state_free(state); | 2521 | drm_atomic_state_put(state); |
| 2538 | state = ERR_PTR(err); | 2522 | state = ERR_PTR(err); |
| 2539 | goto unlock; | 2523 | goto unlock; |
| 2540 | } | 2524 | } |
| @@ -2623,18 +2607,13 @@ retry: | |||
| 2623 | goto fail; | 2607 | goto fail; |
| 2624 | 2608 | ||
| 2625 | ret = drm_atomic_commit(state); | 2609 | ret = drm_atomic_commit(state); |
| 2626 | if (ret != 0) | ||
| 2627 | goto fail; | ||
| 2628 | |||
| 2629 | /* Driver takes ownership of state on successful commit. */ | ||
| 2630 | return 0; | ||
| 2631 | fail: | 2610 | fail: |
| 2632 | if (ret == -EDEADLK) | 2611 | if (ret == -EDEADLK) |
| 2633 | goto backoff; | 2612 | goto backoff; |
| 2634 | 2613 | ||
| 2635 | drm_atomic_state_free(state); | 2614 | drm_atomic_state_put(state); |
| 2636 | |||
| 2637 | return ret; | 2615 | return ret; |
| 2616 | |||
| 2638 | backoff: | 2617 | backoff: |
| 2639 | drm_atomic_state_clear(state); | 2618 | drm_atomic_state_clear(state); |
| 2640 | drm_atomic_legacy_backoff(state); | 2619 | drm_atomic_legacy_backoff(state); |
| @@ -2683,18 +2662,13 @@ retry: | |||
| 2683 | goto fail; | 2662 | goto fail; |
| 2684 | 2663 | ||
| 2685 | ret = drm_atomic_commit(state); | 2664 | ret = drm_atomic_commit(state); |
| 2686 | if (ret != 0) | ||
| 2687 | goto fail; | ||
| 2688 | |||
| 2689 | /* Driver takes ownership of state on successful commit. */ | ||
| 2690 | return 0; | ||
| 2691 | fail: | 2665 | fail: |
| 2692 | if (ret == -EDEADLK) | 2666 | if (ret == -EDEADLK) |
| 2693 | goto backoff; | 2667 | goto backoff; |
| 2694 | 2668 | ||
| 2695 | drm_atomic_state_free(state); | 2669 | drm_atomic_state_put(state); |
| 2696 | |||
| 2697 | return ret; | 2670 | return ret; |
| 2671 | |||
| 2698 | backoff: | 2672 | backoff: |
| 2699 | drm_atomic_state_clear(state); | 2673 | drm_atomic_state_clear(state); |
| 2700 | drm_atomic_legacy_backoff(state); | 2674 | drm_atomic_legacy_backoff(state); |
| @@ -2743,18 +2717,13 @@ retry: | |||
| 2743 | goto fail; | 2717 | goto fail; |
| 2744 | 2718 | ||
| 2745 | ret = drm_atomic_commit(state); | 2719 | ret = drm_atomic_commit(state); |
| 2746 | if (ret != 0) | ||
| 2747 | goto fail; | ||
| 2748 | |||
| 2749 | /* Driver takes ownership of state on successful commit. */ | ||
| 2750 | return 0; | ||
| 2751 | fail: | 2720 | fail: |
| 2752 | if (ret == -EDEADLK) | 2721 | if (ret == -EDEADLK) |
| 2753 | goto backoff; | 2722 | goto backoff; |
| 2754 | 2723 | ||
| 2755 | drm_atomic_state_free(state); | 2724 | drm_atomic_state_put(state); |
| 2756 | |||
| 2757 | return ret; | 2725 | return ret; |
| 2726 | |||
| 2758 | backoff: | 2727 | backoff: |
| 2759 | drm_atomic_state_clear(state); | 2728 | drm_atomic_state_clear(state); |
| 2760 | drm_atomic_legacy_backoff(state); | 2729 | drm_atomic_legacy_backoff(state); |
| @@ -2827,18 +2796,13 @@ retry: | |||
| 2827 | } | 2796 | } |
| 2828 | 2797 | ||
| 2829 | ret = drm_atomic_nonblocking_commit(state); | 2798 | ret = drm_atomic_nonblocking_commit(state); |
| 2830 | if (ret != 0) | ||
| 2831 | goto fail; | ||
| 2832 | |||
| 2833 | /* Driver takes ownership of state on successful commit. */ | ||
| 2834 | return 0; | ||
| 2835 | fail: | 2799 | fail: |
| 2836 | if (ret == -EDEADLK) | 2800 | if (ret == -EDEADLK) |
| 2837 | goto backoff; | 2801 | goto backoff; |
| 2838 | 2802 | ||
| 2839 | drm_atomic_state_free(state); | 2803 | drm_atomic_state_put(state); |
| 2840 | |||
| 2841 | return ret; | 2804 | return ret; |
| 2805 | |||
| 2842 | backoff: | 2806 | backoff: |
| 2843 | drm_atomic_state_clear(state); | 2807 | drm_atomic_state_clear(state); |
| 2844 | drm_atomic_legacy_backoff(state); | 2808 | drm_atomic_legacy_backoff(state); |
| @@ -2914,19 +2878,14 @@ retry: | |||
| 2914 | crtc_state->active = active; | 2878 | crtc_state->active = active; |
| 2915 | 2879 | ||
| 2916 | ret = drm_atomic_commit(state); | 2880 | ret = drm_atomic_commit(state); |
| 2917 | if (ret != 0) | ||
| 2918 | goto fail; | ||
| 2919 | |||
| 2920 | /* Driver takes ownership of state on successful commit. */ | ||
| 2921 | return 0; | ||
| 2922 | fail: | 2881 | fail: |
| 2923 | if (ret == -EDEADLK) | 2882 | if (ret == -EDEADLK) |
| 2924 | goto backoff; | 2883 | goto backoff; |
| 2925 | 2884 | ||
| 2926 | connector->dpms = old_mode; | 2885 | connector->dpms = old_mode; |
| 2927 | drm_atomic_state_free(state); | 2886 | drm_atomic_state_put(state); |
| 2928 | |||
| 2929 | return ret; | 2887 | return ret; |
| 2888 | |||
| 2930 | backoff: | 2889 | backoff: |
| 2931 | drm_atomic_state_clear(state); | 2890 | drm_atomic_state_clear(state); |
| 2932 | drm_atomic_legacy_backoff(state); | 2891 | drm_atomic_legacy_backoff(state); |
| @@ -3333,7 +3292,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev, | |||
| 3333 | 3292 | ||
| 3334 | free: | 3293 | free: |
| 3335 | if (err < 0) { | 3294 | if (err < 0) { |
| 3336 | drm_atomic_state_free(state); | 3295 | drm_atomic_state_put(state); |
| 3337 | state = ERR_PTR(err); | 3296 | state = ERR_PTR(err); |
| 3338 | } | 3297 | } |
| 3339 | 3298 | ||
| @@ -3448,22 +3407,14 @@ retry: | |||
| 3448 | goto fail; | 3407 | goto fail; |
| 3449 | 3408 | ||
| 3450 | ret = drm_atomic_commit(state); | 3409 | ret = drm_atomic_commit(state); |
| 3451 | if (ret) | ||
| 3452 | goto fail; | ||
| 3453 | |||
| 3454 | /* Driver takes ownership of state on successful commit. */ | ||
| 3455 | |||
| 3456 | drm_property_unreference_blob(blob); | ||
| 3457 | |||
| 3458 | return 0; | ||
| 3459 | fail: | 3410 | fail: |
| 3460 | if (ret == -EDEADLK) | 3411 | if (ret == -EDEADLK) |
| 3461 | goto backoff; | 3412 | goto backoff; |
| 3462 | 3413 | ||
| 3463 | drm_atomic_state_free(state); | 3414 | drm_atomic_state_put(state); |
| 3464 | drm_property_unreference_blob(blob); | 3415 | drm_property_unreference_blob(blob); |
| 3465 | |||
| 3466 | return ret; | 3416 | return ret; |
| 3417 | |||
| 3467 | backoff: | 3418 | backoff: |
| 3468 | drm_atomic_state_clear(state); | 3419 | drm_atomic_state_clear(state); |
| 3469 | drm_atomic_legacy_backoff(state); | 3420 | drm_atomic_legacy_backoff(state); |
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index 85172a977bf3..e52aece30900 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c | |||
| @@ -162,6 +162,41 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, | |||
| 162 | } | 162 | } |
| 163 | EXPORT_SYMBOL(drm_mode_create_rotation_property); | 163 | EXPORT_SYMBOL(drm_mode_create_rotation_property); |
| 164 | 164 | ||
| 165 | int drm_plane_create_rotation_property(struct drm_plane *plane, | ||
| 166 | unsigned int rotation, | ||
| 167 | unsigned int supported_rotations) | ||
| 168 | { | ||
| 169 | static const struct drm_prop_enum_list props[] = { | ||
| 170 | { __builtin_ffs(DRM_ROTATE_0) - 1, "rotate-0" }, | ||
| 171 | { __builtin_ffs(DRM_ROTATE_90) - 1, "rotate-90" }, | ||
| 172 | { __builtin_ffs(DRM_ROTATE_180) - 1, "rotate-180" }, | ||
| 173 | { __builtin_ffs(DRM_ROTATE_270) - 1, "rotate-270" }, | ||
| 174 | { __builtin_ffs(DRM_REFLECT_X) - 1, "reflect-x" }, | ||
| 175 | { __builtin_ffs(DRM_REFLECT_Y) - 1, "reflect-y" }, | ||
| 176 | }; | ||
| 177 | struct drm_property *prop; | ||
| 178 | |||
| 179 | WARN_ON((supported_rotations & DRM_ROTATE_MASK) == 0); | ||
| 180 | WARN_ON(!is_power_of_2(rotation & DRM_ROTATE_MASK)); | ||
| 181 | WARN_ON(rotation & ~supported_rotations); | ||
| 182 | |||
| 183 | prop = drm_property_create_bitmask(plane->dev, 0, "rotation", | ||
| 184 | props, ARRAY_SIZE(props), | ||
| 185 | supported_rotations); | ||
| 186 | if (!prop) | ||
| 187 | return -ENOMEM; | ||
| 188 | |||
| 189 | drm_object_attach_property(&plane->base, prop, rotation); | ||
| 190 | |||
| 191 | if (plane->state) | ||
| 192 | plane->state->rotation = rotation; | ||
| 193 | |||
| 194 | plane->rotation_property = prop; | ||
| 195 | |||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | EXPORT_SYMBOL(drm_plane_create_rotation_property); | ||
| 199 | |||
| 165 | /** | 200 | /** |
| 166 | * drm_rotation_simplify() - Try to simplify the rotation | 201 | * drm_rotation_simplify() - Try to simplify the rotation |
| 167 | * @rotation: Rotation to be simplified | 202 | * @rotation: Rotation to be simplified |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 2d7bedf28647..13441e21117c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | #include <drm/drm_modeset_lock.h> | 40 | #include <drm/drm_modeset_lock.h> |
| 41 | #include <drm/drm_atomic.h> | 41 | #include <drm/drm_atomic.h> |
| 42 | #include <drm/drm_auth.h> | 42 | #include <drm/drm_auth.h> |
| 43 | #include <drm/drm_framebuffer.h> | 43 | #include <drm/drm_debugfs_crc.h> |
| 44 | 44 | ||
| 45 | #include "drm_crtc_internal.h" | 45 | #include "drm_crtc_internal.h" |
| 46 | #include "drm_internal.h" | 46 | #include "drm_internal.h" |
| @@ -122,6 +122,10 @@ static int drm_crtc_register_all(struct drm_device *dev) | |||
| 122 | int ret = 0; | 122 | int ret = 0; |
| 123 | 123 | ||
| 124 | drm_for_each_crtc(crtc, dev) { | 124 | drm_for_each_crtc(crtc, dev) { |
| 125 | if (drm_debugfs_crtc_add(crtc)) | ||
| 126 | DRM_ERROR("Failed to initialize debugfs entry for CRTC '%s'.\n", | ||
| 127 | crtc->name); | ||
| 128 | |||
| 125 | if (crtc->funcs->late_register) | 129 | if (crtc->funcs->late_register) |
| 126 | ret = crtc->funcs->late_register(crtc); | 130 | ret = crtc->funcs->late_register(crtc); |
| 127 | if (ret) | 131 | if (ret) |
| @@ -138,9 +142,29 @@ static void drm_crtc_unregister_all(struct drm_device *dev) | |||
| 138 | drm_for_each_crtc(crtc, dev) { | 142 | drm_for_each_crtc(crtc, dev) { |
| 139 | if (crtc->funcs->early_unregister) | 143 | if (crtc->funcs->early_unregister) |
| 140 | crtc->funcs->early_unregister(crtc); | 144 | crtc->funcs->early_unregister(crtc); |
| 145 | drm_debugfs_crtc_remove(crtc); | ||
| 141 | } | 146 | } |
| 142 | } | 147 | } |
| 143 | 148 | ||
| 149 | static int drm_crtc_crc_init(struct drm_crtc *crtc) | ||
| 150 | { | ||
| 151 | #ifdef CONFIG_DEBUG_FS | ||
| 152 | spin_lock_init(&crtc->crc.lock); | ||
| 153 | init_waitqueue_head(&crtc->crc.wq); | ||
| 154 | crtc->crc.source = kstrdup("auto", GFP_KERNEL); | ||
| 155 | if (!crtc->crc.source) | ||
| 156 | return -ENOMEM; | ||
| 157 | #endif | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static void drm_crtc_crc_fini(struct drm_crtc *crtc) | ||
| 162 | { | ||
| 163 | #ifdef CONFIG_DEBUG_FS | ||
| 164 | kfree(crtc->crc.source); | ||
| 165 | #endif | ||
| 166 | } | ||
| 167 | |||
| 144 | /** | 168 | /** |
| 145 | * drm_crtc_init_with_planes - Initialise a new CRTC object with | 169 | * drm_crtc_init_with_planes - Initialise a new CRTC object with |
| 146 | * specified primary and cursor planes. | 170 | * specified primary and cursor planes. |
| @@ -210,6 +234,12 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, | |||
| 210 | if (cursor) | 234 | if (cursor) |
| 211 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); | 235 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); |
| 212 | 236 | ||
| 237 | ret = drm_crtc_crc_init(crtc); | ||
| 238 | if (ret) { | ||
| 239 | drm_mode_object_unregister(dev, &crtc->base); | ||
| 240 | return ret; | ||
| 241 | } | ||
| 242 | |||
| 213 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { | 243 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { |
| 214 | drm_object_attach_property(&crtc->base, config->prop_active, 0); | 244 | drm_object_attach_property(&crtc->base, config->prop_active, 0); |
| 215 | drm_object_attach_property(&crtc->base, config->prop_mode_id, 0); | 245 | drm_object_attach_property(&crtc->base, config->prop_mode_id, 0); |
| @@ -236,6 +266,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) | |||
| 236 | * the indices on the drm_crtc after us in the crtc_list. | 266 | * the indices on the drm_crtc after us in the crtc_list. |
| 237 | */ | 267 | */ |
| 238 | 268 | ||
| 269 | drm_crtc_crc_fini(crtc); | ||
| 270 | |||
| 239 | kfree(crtc->gamma_store); | 271 | kfree(crtc->gamma_store); |
| 240 | crtc->gamma_store = NULL; | 272 | crtc->gamma_store = NULL; |
| 241 | 273 | ||
| @@ -695,8 +727,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, | |||
| 695 | drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); | 727 | drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); |
| 696 | 728 | ||
| 697 | if (crtc->state && | 729 | if (crtc->state && |
| 698 | crtc->primary->state->rotation & (DRM_ROTATE_90 | | 730 | drm_rotation_90_or_270(crtc->primary->state->rotation)) |
| 699 | DRM_ROTATE_270)) | ||
| 700 | swap(hdisplay, vdisplay); | 731 | swap(hdisplay, vdisplay); |
| 701 | 732 | ||
| 702 | return drm_framebuffer_check_src_coords(x << 16, y << 16, | 733 | return drm_framebuffer_check_src_coords(x << 16, y << 16, |
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 1205790ed960..800055c39cdb 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c | |||
| @@ -415,5 +415,37 @@ void drm_debugfs_connector_remove(struct drm_connector *connector) | |||
| 415 | connector->debugfs_entry = NULL; | 415 | connector->debugfs_entry = NULL; |
| 416 | } | 416 | } |
| 417 | 417 | ||
| 418 | #endif /* CONFIG_DEBUG_FS */ | 418 | int drm_debugfs_crtc_add(struct drm_crtc *crtc) |
| 419 | { | ||
| 420 | struct drm_minor *minor = crtc->dev->primary; | ||
| 421 | struct dentry *root; | ||
| 422 | char *name; | ||
| 423 | |||
| 424 | name = kasprintf(GFP_KERNEL, "crtc-%d", crtc->index); | ||
| 425 | if (!name) | ||
| 426 | return -ENOMEM; | ||
| 427 | |||
| 428 | root = debugfs_create_dir(name, minor->debugfs_root); | ||
| 429 | kfree(name); | ||
| 430 | if (!root) | ||
| 431 | return -ENOMEM; | ||
| 432 | |||
| 433 | crtc->debugfs_entry = root; | ||
| 434 | |||
| 435 | if (drm_debugfs_crtc_crc_add(crtc)) | ||
| 436 | goto error; | ||
| 419 | 437 | ||
| 438 | return 0; | ||
| 439 | |||
| 440 | error: | ||
| 441 | drm_debugfs_crtc_remove(crtc); | ||
| 442 | return -ENOMEM; | ||
| 443 | } | ||
| 444 | |||
| 445 | void drm_debugfs_crtc_remove(struct drm_crtc *crtc) | ||
| 446 | { | ||
| 447 | debugfs_remove_recursive(crtc->debugfs_entry); | ||
| 448 | crtc->debugfs_entry = NULL; | ||
| 449 | } | ||
| 450 | |||
| 451 | #endif /* CONFIG_DEBUG_FS */ | ||
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c new file mode 100644 index 000000000000..00e771fb7df2 --- /dev/null +++ b/drivers/gpu/drm/drm_debugfs_crc.c | |||
| @@ -0,0 +1,352 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2008 Intel Corporation | ||
| 3 | * Copyright © 2016 Collabora Ltd | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice (including the next | ||
| 13 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 14 | * Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 22 | * IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Based on code from the i915 driver. | ||
| 25 | * Original author: Damien Lespiau <damien.lespiau@intel.com> | ||
| 26 | * | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/circ_buf.h> | ||
| 30 | #include <linux/ctype.h> | ||
| 31 | #include <linux/debugfs.h> | ||
| 32 | #include <drm/drmP.h> | ||
| 33 | #include "drm_internal.h" | ||
| 34 | |||
| 35 | /** | ||
| 36 | * DOC: CRC ABI | ||
| 37 | * | ||
| 38 | * DRM device drivers can provide to userspace CRC information of each frame as | ||
| 39 | * it reached a given hardware component (a "source"). | ||
| 40 | * | ||
| 41 | * Userspace can control generation of CRCs in a given CRTC by writing to the | ||
| 42 | * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC. | ||
| 43 | * Accepted values are source names (which are driver-specific) and the "auto" | ||
| 44 | * keyword, which will let the driver select a default source of frame CRCs | ||
| 45 | * for this CRTC. | ||
| 46 | * | ||
| 47 | * Once frame CRC generation is enabled, userspace can capture them by reading | ||
| 48 | * the dri/0/crtc-N/crc/data file. Each line in that file contains the frame | ||
| 49 | * number in the first field and then a number of unsigned integer fields | ||
| 50 | * containing the CRC data. Fields are separated by a single space and the number | ||
| 51 | * of CRC fields is source-specific. | ||
| 52 | * | ||
| 53 | * Note that though in some cases the CRC is computed in a specified way and on | ||
| 54 | * the frame contents as supplied by userspace (eDP 1.3), in general the CRC | ||
| 55 | * computation is performed in an unspecified way and on frame contents that have | ||
| 56 | * been already processed in also an unspecified way and thus userspace cannot | ||
| 57 | * rely on being able to generate matching CRC values for the frame contents that | ||
| 58 | * it submits. In this general case, the maximum userspace can do is to compare | ||
| 59 | * the reported CRCs of frames that should have the same contents. | ||
| 60 | */ | ||
| 61 | |||
| 62 | static int crc_control_show(struct seq_file *m, void *data) | ||
| 63 | { | ||
| 64 | struct drm_crtc *crtc = m->private; | ||
| 65 | |||
| 66 | seq_printf(m, "%s\n", crtc->crc.source); | ||
| 67 | |||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | static int crc_control_open(struct inode *inode, struct file *file) | ||
| 72 | { | ||
| 73 | struct drm_crtc *crtc = inode->i_private; | ||
| 74 | |||
| 75 | return single_open(file, crc_control_show, crtc); | ||
| 76 | } | ||
| 77 | |||
| 78 | static ssize_t crc_control_write(struct file *file, const char __user *ubuf, | ||
| 79 | size_t len, loff_t *offp) | ||
| 80 | { | ||
| 81 | struct seq_file *m = file->private_data; | ||
| 82 | struct drm_crtc *crtc = m->private; | ||
| 83 | struct drm_crtc_crc *crc = &crtc->crc; | ||
| 84 | char *source; | ||
| 85 | |||
| 86 | if (len == 0) | ||
| 87 | return 0; | ||
| 88 | |||
| 89 | if (len > PAGE_SIZE - 1) { | ||
| 90 | DRM_DEBUG_KMS("Expected < %lu bytes into crtc crc control\n", | ||
| 91 | PAGE_SIZE); | ||
| 92 | return -E2BIG; | ||
| 93 | } | ||
| 94 | |||
| 95 | source = memdup_user_nul(ubuf, len); | ||
| 96 | if (IS_ERR(source)) | ||
| 97 | return PTR_ERR(source); | ||
| 98 | |||
| 99 | if (source[len] == '\n') | ||
| 100 | source[len] = '\0'; | ||
| 101 | |||
| 102 | spin_lock_irq(&crc->lock); | ||
| 103 | |||
| 104 | if (crc->opened) { | ||
| 105 | spin_unlock_irq(&crc->lock); | ||
| 106 | kfree(source); | ||
| 107 | return -EBUSY; | ||
| 108 | } | ||
| 109 | |||
| 110 | kfree(crc->source); | ||
| 111 | crc->source = source; | ||
| 112 | |||
| 113 | spin_unlock_irq(&crc->lock); | ||
| 114 | |||
| 115 | *offp += len; | ||
| 116 | return len; | ||
| 117 | } | ||
| 118 | |||
| 119 | static const struct file_operations drm_crtc_crc_control_fops = { | ||
| 120 | .owner = THIS_MODULE, | ||
| 121 | .open = crc_control_open, | ||
| 122 | .read = seq_read, | ||
| 123 | .llseek = seq_lseek, | ||
| 124 | .release = single_release, | ||
| 125 | .write = crc_control_write | ||
| 126 | }; | ||
| 127 | |||
| 128 | static int crtc_crc_open(struct inode *inode, struct file *filep) | ||
| 129 | { | ||
| 130 | struct drm_crtc *crtc = inode->i_private; | ||
| 131 | struct drm_crtc_crc *crc = &crtc->crc; | ||
| 132 | struct drm_crtc_crc_entry *entries = NULL; | ||
| 133 | size_t values_cnt; | ||
| 134 | int ret; | ||
| 135 | |||
| 136 | if (crc->opened) | ||
| 137 | return -EBUSY; | ||
| 138 | |||
| 139 | ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt); | ||
| 140 | if (ret) | ||
| 141 | return ret; | ||
| 142 | |||
| 143 | if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) { | ||
| 144 | ret = -EINVAL; | ||
| 145 | goto err_disable; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (WARN_ON(values_cnt == 0)) { | ||
| 149 | ret = -EINVAL; | ||
| 150 | goto err_disable; | ||
| 151 | } | ||
| 152 | |||
| 153 | entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL); | ||
| 154 | if (!entries) { | ||
| 155 | ret = -ENOMEM; | ||
| 156 | goto err_disable; | ||
| 157 | } | ||
| 158 | |||
| 159 | spin_lock_irq(&crc->lock); | ||
| 160 | crc->entries = entries; | ||
| 161 | crc->values_cnt = values_cnt; | ||
| 162 | crc->opened = true; | ||
| 163 | spin_unlock_irq(&crc->lock); | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | |||
| 167 | err_disable: | ||
| 168 | crtc->funcs->set_crc_source(crtc, NULL, &values_cnt); | ||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | |||
| 172 | static int crtc_crc_release(struct inode *inode, struct file *filep) | ||
| 173 | { | ||
| 174 | struct drm_crtc *crtc = filep->f_inode->i_private; | ||
| 175 | struct drm_crtc_crc *crc = &crtc->crc; | ||
| 176 | size_t values_cnt; | ||
| 177 | |||
| 178 | spin_lock_irq(&crc->lock); | ||
| 179 | kfree(crc->entries); | ||
| 180 | crc->entries = NULL; | ||
| 181 | crc->head = 0; | ||
| 182 | crc->tail = 0; | ||
| 183 | crc->values_cnt = 0; | ||
| 184 | crc->opened = false; | ||
| 185 | spin_unlock_irq(&crc->lock); | ||
| 186 | |||
| 187 | crtc->funcs->set_crc_source(crtc, NULL, &values_cnt); | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int crtc_crc_data_count(struct drm_crtc_crc *crc) | ||
| 193 | { | ||
| 194 | assert_spin_locked(&crc->lock); | ||
| 195 | return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR); | ||
| 196 | } | ||
| 197 | |||
| 198 | /* | ||
| 199 | * 1 frame field of 10 chars plus a number of CRC fields of 10 chars each, space | ||
| 200 | * separated, with a newline at the end and null-terminated. | ||
| 201 | */ | ||
| 202 | #define LINE_LEN(values_cnt) (10 + 11 * values_cnt + 1 + 1) | ||
| 203 | #define MAX_LINE_LEN (LINE_LEN(DRM_MAX_CRC_NR)) | ||
| 204 | |||
| 205 | static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf, | ||
| 206 | size_t count, loff_t *pos) | ||
| 207 | { | ||
| 208 | struct drm_crtc *crtc = filep->f_inode->i_private; | ||
| 209 | struct drm_crtc_crc *crc = &crtc->crc; | ||
| 210 | struct drm_crtc_crc_entry *entry; | ||
| 211 | char buf[MAX_LINE_LEN]; | ||
| 212 | int ret, i; | ||
| 213 | |||
| 214 | spin_lock_irq(&crc->lock); | ||
| 215 | |||
| 216 | if (!crc->source) { | ||
| 217 | spin_unlock_irq(&crc->lock); | ||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | |||
| 221 | /* Nothing to read? */ | ||
| 222 | while (crtc_crc_data_count(crc) == 0) { | ||
| 223 | if (filep->f_flags & O_NONBLOCK) { | ||
| 224 | spin_unlock_irq(&crc->lock); | ||
| 225 | return -EAGAIN; | ||
| 226 | } | ||
| 227 | |||
| 228 | ret = wait_event_interruptible_lock_irq(crc->wq, | ||
| 229 | crtc_crc_data_count(crc), | ||
| 230 | crc->lock); | ||
| 231 | if (ret) { | ||
| 232 | spin_unlock_irq(&crc->lock); | ||
| 233 | return ret; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | /* We know we have an entry to be read */ | ||
| 238 | entry = &crc->entries[crc->tail]; | ||
| 239 | |||
| 240 | if (count < LINE_LEN(crc->values_cnt)) { | ||
| 241 | spin_unlock_irq(&crc->lock); | ||
| 242 | return -EINVAL; | ||
| 243 | } | ||
| 244 | |||
| 245 | BUILD_BUG_ON_NOT_POWER_OF_2(DRM_CRC_ENTRIES_NR); | ||
| 246 | crc->tail = (crc->tail + 1) & (DRM_CRC_ENTRIES_NR - 1); | ||
| 247 | |||
| 248 | spin_unlock_irq(&crc->lock); | ||
| 249 | |||
| 250 | if (entry->has_frame_counter) | ||
| 251 | sprintf(buf, "0x%08x", entry->frame); | ||
| 252 | else | ||
| 253 | sprintf(buf, "XXXXXXXXXX"); | ||
| 254 | |||
| 255 | for (i = 0; i < crc->values_cnt; i++) | ||
| 256 | sprintf(buf + 10 + i * 11, " 0x%08x", entry->crcs[i]); | ||
| 257 | sprintf(buf + 10 + crc->values_cnt * 11, "\n"); | ||
| 258 | |||
| 259 | if (copy_to_user(user_buf, buf, LINE_LEN(crc->values_cnt))) | ||
| 260 | return -EFAULT; | ||
| 261 | |||
| 262 | return LINE_LEN(crc->values_cnt); | ||
| 263 | } | ||
| 264 | |||
| 265 | static const struct file_operations drm_crtc_crc_data_fops = { | ||
| 266 | .owner = THIS_MODULE, | ||
| 267 | .open = crtc_crc_open, | ||
| 268 | .read = crtc_crc_read, | ||
| 269 | .release = crtc_crc_release, | ||
| 270 | }; | ||
| 271 | |||
| 272 | /** | ||
| 273 | * drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs | ||
| 274 | * @crtc: CRTC to whom the frames will belong | ||
| 275 | * | ||
| 276 | * Adds files to debugfs directory that allows userspace to control the | ||
| 277 | * generation of frame CRCs and to read them. | ||
| 278 | * | ||
| 279 | * Returns: | ||
| 280 | * Zero on success, error code on failure. | ||
| 281 | */ | ||
| 282 | int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) | ||
| 283 | { | ||
| 284 | struct dentry *crc_ent, *ent; | ||
| 285 | |||
| 286 | if (!crtc->funcs->set_crc_source) | ||
| 287 | return 0; | ||
| 288 | |||
| 289 | crc_ent = debugfs_create_dir("crc", crtc->debugfs_entry); | ||
| 290 | if (!crc_ent) | ||
| 291 | return -ENOMEM; | ||
| 292 | |||
| 293 | ent = debugfs_create_file("control", S_IRUGO, crc_ent, crtc, | ||
| 294 | &drm_crtc_crc_control_fops); | ||
| 295 | if (!ent) | ||
| 296 | goto error; | ||
| 297 | |||
| 298 | ent = debugfs_create_file("data", S_IRUGO, crc_ent, crtc, | ||
| 299 | &drm_crtc_crc_data_fops); | ||
| 300 | if (!ent) | ||
| 301 | goto error; | ||
| 302 | |||
| 303 | return 0; | ||
| 304 | |||
| 305 | error: | ||
| 306 | debugfs_remove_recursive(crc_ent); | ||
| 307 | |||
| 308 | return -ENOMEM; | ||
| 309 | } | ||
| 310 | |||
| 311 | /** | ||
| 312 | * drm_crtc_add_crc_entry - Add entry with CRC information for a frame | ||
| 313 | * @crtc: CRTC to which the frame belongs | ||
| 314 | * @has_frame: whether this entry has a frame number to go with | ||
| 315 | * @frame: number of the frame these CRCs are about | ||
| 316 | * @crcs: array of CRC values, with length matching #drm_crtc_crc.values_cnt | ||
| 317 | * | ||
| 318 | * For each frame, the driver polls the source of CRCs for new data and calls | ||
| 319 | * this function to add them to the buffer from where userspace reads. | ||
| 320 | */ | ||
| 321 | int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, | ||
| 322 | uint32_t frame, uint32_t *crcs) | ||
| 323 | { | ||
| 324 | struct drm_crtc_crc *crc = &crtc->crc; | ||
| 325 | struct drm_crtc_crc_entry *entry; | ||
| 326 | int head, tail; | ||
| 327 | |||
| 328 | assert_spin_locked(&crc->lock); | ||
| 329 | |||
| 330 | /* Caller may not have noticed yet that userspace has stopped reading */ | ||
| 331 | if (!crc->opened) | ||
| 332 | return -EINVAL; | ||
| 333 | |||
| 334 | head = crc->head; | ||
| 335 | tail = crc->tail; | ||
| 336 | |||
| 337 | if (CIRC_SPACE(head, tail, DRM_CRC_ENTRIES_NR) < 1) { | ||
| 338 | DRM_ERROR("Overflow of CRC buffer, userspace reads too slow.\n"); | ||
| 339 | return -ENOBUFS; | ||
| 340 | } | ||
| 341 | |||
| 342 | entry = &crc->entries[head]; | ||
| 343 | entry->frame = frame; | ||
| 344 | entry->has_frame_counter = has_frame; | ||
| 345 | memcpy(&entry->crcs, crcs, sizeof(*crcs) * crc->values_cnt); | ||
| 346 | |||
| 347 | head = (head + 1) & (DRM_CRC_ENTRIES_NR - 1); | ||
| 348 | crc->head = head; | ||
| 349 | |||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | EXPORT_SYMBOL_GPL(drm_crtc_add_crc_entry); | ||
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ec77bd3e1f08..95de47ba1e77 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -1282,20 +1282,20 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, | |||
| 1282 | void *data) | 1282 | void *data) |
| 1283 | { | 1283 | { |
| 1284 | int i, j = 0, valid_extensions = 0; | 1284 | int i, j = 0, valid_extensions = 0; |
| 1285 | u8 *block, *new; | 1285 | u8 *edid, *new; |
| 1286 | bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS); | 1286 | bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS); |
| 1287 | 1287 | ||
| 1288 | if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) | 1288 | if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) |
| 1289 | return NULL; | 1289 | return NULL; |
| 1290 | 1290 | ||
| 1291 | /* base block fetch */ | 1291 | /* base block fetch */ |
| 1292 | for (i = 0; i < 4; i++) { | 1292 | for (i = 0; i < 4; i++) { |
| 1293 | if (get_edid_block(data, block, 0, EDID_LENGTH)) | 1293 | if (get_edid_block(data, edid, 0, EDID_LENGTH)) |
| 1294 | goto out; | 1294 | goto out; |
| 1295 | if (drm_edid_block_valid(block, 0, print_bad_edid, | 1295 | if (drm_edid_block_valid(edid, 0, print_bad_edid, |
| 1296 | &connector->edid_corrupt)) | 1296 | &connector->edid_corrupt)) |
| 1297 | break; | 1297 | break; |
| 1298 | if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { | 1298 | if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) { |
| 1299 | connector->null_edid_counter++; | 1299 | connector->null_edid_counter++; |
| 1300 | goto carp; | 1300 | goto carp; |
| 1301 | } | 1301 | } |
| @@ -1304,24 +1304,22 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, | |||
| 1304 | goto carp; | 1304 | goto carp; |
| 1305 | 1305 | ||
| 1306 | /* if there's no extensions, we're done */ | 1306 | /* if there's no extensions, we're done */ |
| 1307 | if (block[0x7e] == 0) | 1307 | if (edid[0x7e] == 0) |
| 1308 | return (struct edid *)block; | 1308 | return (struct edid *)edid; |
| 1309 | 1309 | ||
| 1310 | new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); | 1310 | new = krealloc(edid, (edid[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); |
| 1311 | if (!new) | 1311 | if (!new) |
| 1312 | goto out; | 1312 | goto out; |
| 1313 | block = new; | 1313 | edid = new; |
| 1314 | |||
| 1315 | for (j = 1; j <= edid[0x7e]; j++) { | ||
| 1316 | u8 *block = edid + (valid_extensions + 1) * EDID_LENGTH; | ||
| 1314 | 1317 | ||
| 1315 | for (j = 1; j <= block[0x7e]; j++) { | ||
| 1316 | for (i = 0; i < 4; i++) { | 1318 | for (i = 0; i < 4; i++) { |
| 1317 | if (get_edid_block(data, | 1319 | if (get_edid_block(data, block, j, EDID_LENGTH)) |
| 1318 | block + (valid_extensions + 1) * EDID_LENGTH, | ||
| 1319 | j, EDID_LENGTH)) | ||
| 1320 | goto out; | 1320 | goto out; |
| 1321 | if (drm_edid_block_valid(block + (valid_extensions + 1) | 1321 | if (drm_edid_block_valid(block, j, |
| 1322 | * EDID_LENGTH, j, | 1322 | print_bad_edid, NULL)) { |
| 1323 | print_bad_edid, | ||
| 1324 | NULL)) { | ||
| 1325 | valid_extensions++; | 1323 | valid_extensions++; |
| 1326 | break; | 1324 | break; |
| 1327 | } | 1325 | } |
| @@ -1336,16 +1334,16 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, | |||
| 1336 | } | 1334 | } |
| 1337 | } | 1335 | } |
| 1338 | 1336 | ||
| 1339 | if (valid_extensions != block[0x7e]) { | 1337 | if (valid_extensions != edid[0x7e]) { |
| 1340 | block[EDID_LENGTH-1] += block[0x7e] - valid_extensions; | 1338 | edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions; |
| 1341 | block[0x7e] = valid_extensions; | 1339 | edid[0x7e] = valid_extensions; |
| 1342 | new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); | 1340 | new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); |
| 1343 | if (!new) | 1341 | if (!new) |
| 1344 | goto out; | 1342 | goto out; |
| 1345 | block = new; | 1343 | edid = new; |
| 1346 | } | 1344 | } |
| 1347 | 1345 | ||
| 1348 | return (struct edid *)block; | 1346 | return (struct edid *)edid; |
| 1349 | 1347 | ||
| 1350 | carp: | 1348 | carp: |
| 1351 | if (print_bad_edid) { | 1349 | if (print_bad_edid) { |
| @@ -1355,7 +1353,7 @@ carp: | |||
| 1355 | connector->bad_edid_counter++; | 1353 | connector->bad_edid_counter++; |
| 1356 | 1354 | ||
| 1357 | out: | 1355 | out: |
| 1358 | kfree(block); | 1356 | kfree(edid); |
| 1359 | return NULL; | 1357 | return NULL; |
| 1360 | } | 1358 | } |
| 1361 | EXPORT_SYMBOL_GPL(drm_do_get_edid); | 1359 | EXPORT_SYMBOL_GPL(drm_do_get_edid); |
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 1fd6eac1400c..4c6664407bfb 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c | |||
| @@ -176,20 +176,20 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, | |||
| 176 | struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, | 176 | struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, |
| 177 | const struct drm_framebuffer_funcs *funcs) | 177 | const struct drm_framebuffer_funcs *funcs) |
| 178 | { | 178 | { |
| 179 | const struct drm_format_info *info; | ||
| 179 | struct drm_fb_cma *fb_cma; | 180 | struct drm_fb_cma *fb_cma; |
| 180 | struct drm_gem_cma_object *objs[4]; | 181 | struct drm_gem_cma_object *objs[4]; |
| 181 | struct drm_gem_object *obj; | 182 | struct drm_gem_object *obj; |
| 182 | unsigned int hsub; | ||
| 183 | unsigned int vsub; | ||
| 184 | int ret; | 183 | int ret; |
| 185 | int i; | 184 | int i; |
| 186 | 185 | ||
| 187 | hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); | 186 | info = drm_format_info(mode_cmd->pixel_format); |
| 188 | vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); | 187 | if (!info) |
| 188 | return ERR_PTR(-EINVAL); | ||
| 189 | 189 | ||
| 190 | for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) { | 190 | for (i = 0; i < info->num_planes; i++) { |
| 191 | unsigned int width = mode_cmd->width / (i ? hsub : 1); | 191 | unsigned int width = mode_cmd->width / (i ? info->hsub : 1); |
| 192 | unsigned int height = mode_cmd->height / (i ? vsub : 1); | 192 | unsigned int height = mode_cmd->height / (i ? info->vsub : 1); |
| 193 | unsigned int min_size; | 193 | unsigned int min_size; |
| 194 | 194 | ||
| 195 | obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); | 195 | obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); |
| @@ -200,7 +200,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, | |||
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | min_size = (height - 1) * mode_cmd->pitches[i] | 202 | min_size = (height - 1) * mode_cmd->pitches[i] |
| 203 | + width * drm_format_plane_cpp(mode_cmd->pixel_format, i) | 203 | + width * info->cpp[i] |
| 204 | + mode_cmd->offsets[i]; | 204 | + mode_cmd->offsets[i]; |
| 205 | 205 | ||
| 206 | if (obj->size < min_size) { | 206 | if (obj->size < min_size) { |
| @@ -269,12 +269,15 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); | |||
| 269 | static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) | 269 | static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) |
| 270 | { | 270 | { |
| 271 | struct drm_fb_cma *fb_cma = to_fb_cma(fb); | 271 | struct drm_fb_cma *fb_cma = to_fb_cma(fb); |
| 272 | int i, n = drm_format_num_planes(fb->pixel_format); | 272 | const struct drm_format_info *info; |
| 273 | int i; | ||
| 273 | 274 | ||
| 274 | seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, | 275 | seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, |
| 275 | (char *)&fb->pixel_format); | 276 | (char *)&fb->pixel_format); |
| 276 | 277 | ||
| 277 | for (i = 0; i < n; i++) { | 278 | info = drm_format_info(fb->pixel_format); |
| 279 | |||
| 280 | for (i = 0; i < info->num_planes; i++) { | ||
| 278 | seq_printf(m, " %d: offset=%d pitch=%d, obj: ", | 281 | seq_printf(m, " %d: offset=%d pitch=%d, obj: ", |
| 279 | i, fb->offsets[i], fb->pitches[i]); | 282 | i, fb->offsets[i], fb->pitches[i]); |
| 280 | drm_gem_cma_describe(fb_cma->obj[i], m); | 283 | drm_gem_cma_describe(fb_cma->obj[i], m); |
| @@ -557,7 +560,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init); | |||
| 557 | void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma) | 560 | void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma) |
| 558 | { | 561 | { |
| 559 | drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper); | 562 | drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper); |
| 560 | drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev); | 563 | if (fbdev_cma->fb_helper.fbdev) |
| 564 | drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev); | ||
| 561 | drm_fb_helper_release_fbi(&fbdev_cma->fb_helper); | 565 | drm_fb_helper_release_fbi(&fbdev_cma->fb_helper); |
| 562 | 566 | ||
| 563 | if (fbdev_cma->fb) { | 567 | if (fbdev_cma->fb) { |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 03414bde1f15..e0d428f9d1cb 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
| @@ -367,9 +367,7 @@ fail: | |||
| 367 | if (ret == -EDEADLK) | 367 | if (ret == -EDEADLK) |
| 368 | goto backoff; | 368 | goto backoff; |
| 369 | 369 | ||
| 370 | if (ret != 0) | 370 | drm_atomic_state_put(state); |
| 371 | drm_atomic_state_free(state); | ||
| 372 | |||
| 373 | return ret; | 371 | return ret; |
| 374 | 372 | ||
| 375 | backoff: | 373 | backoff: |
| @@ -394,7 +392,11 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) | |||
| 394 | if (plane->type != DRM_PLANE_TYPE_PRIMARY) | 392 | if (plane->type != DRM_PLANE_TYPE_PRIMARY) |
| 395 | drm_plane_force_disable(plane); | 393 | drm_plane_force_disable(plane); |
| 396 | 394 | ||
| 397 | if (dev->mode_config.rotation_property) { | 395 | if (plane->rotation_property) { |
| 396 | drm_mode_plane_set_obj_prop(plane, | ||
| 397 | plane->rotation_property, | ||
| 398 | DRM_ROTATE_0); | ||
| 399 | } else if (dev->mode_config.rotation_property) { | ||
| 398 | drm_mode_plane_set_obj_prop(plane, | 400 | drm_mode_plane_set_obj_prop(plane, |
| 399 | dev->mode_config.rotation_property, | 401 | dev->mode_config.rotation_property, |
| 400 | DRM_ROTATE_0); | 402 | DRM_ROTATE_0); |
| @@ -1211,11 +1213,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, | |||
| 1211 | if (var->pixclock != 0 || in_dbg_master()) | 1213 | if (var->pixclock != 0 || in_dbg_master()) |
| 1212 | return -EINVAL; | 1214 | return -EINVAL; |
| 1213 | 1215 | ||
| 1214 | /* Need to resize the fb object !!! */ | 1216 | /* |
| 1215 | if (var->bits_per_pixel > fb->bits_per_pixel || | 1217 | * Changes struct fb_var_screeninfo are currently not pushed back |
| 1216 | var->xres > fb->width || var->yres > fb->height || | 1218 | * to KMS, hence fail if different settings are requested. |
| 1217 | var->xres_virtual > fb->width || var->yres_virtual > fb->height) { | 1219 | */ |
| 1218 | DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb " | 1220 | if (var->bits_per_pixel != fb->bits_per_pixel || |
| 1221 | var->xres != fb->width || var->yres != fb->height || | ||
| 1222 | var->xres_virtual != fb->width || var->yres_virtual != fb->height) { | ||
| 1223 | DRM_DEBUG("fb userspace requested width/height/bpp different than current fb " | ||
| 1219 | "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", | 1224 | "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", |
| 1220 | var->xres, var->yres, var->bits_per_pixel, | 1225 | var->xres, var->yres, var->bits_per_pixel, |
| 1221 | var->xres_virtual, var->yres_virtual, | 1226 | var->xres_virtual, var->yres_virtual, |
| @@ -1361,16 +1366,13 @@ retry: | |||
| 1361 | info->var.xoffset = var->xoffset; | 1366 | info->var.xoffset = var->xoffset; |
| 1362 | info->var.yoffset = var->yoffset; | 1367 | info->var.yoffset = var->yoffset; |
| 1363 | 1368 | ||
| 1364 | |||
| 1365 | fail: | 1369 | fail: |
| 1366 | drm_atomic_clean_old_fb(dev, plane_mask, ret); | 1370 | drm_atomic_clean_old_fb(dev, plane_mask, ret); |
| 1367 | 1371 | ||
| 1368 | if (ret == -EDEADLK) | 1372 | if (ret == -EDEADLK) |
| 1369 | goto backoff; | 1373 | goto backoff; |
| 1370 | 1374 | ||
| 1371 | if (ret != 0) | 1375 | drm_atomic_state_put(state); |
| 1372 | drm_atomic_state_free(state); | ||
| 1373 | |||
| 1374 | return ret; | 1376 | return ret; |
| 1375 | 1377 | ||
| 1376 | backoff: | 1378 | backoff: |
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index e84faecf5225..8bed5f459182 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
| @@ -663,6 +663,10 @@ void drm_event_cancel_free(struct drm_device *dev, | |||
| 663 | list_del(&p->pending_link); | 663 | list_del(&p->pending_link); |
| 664 | } | 664 | } |
| 665 | spin_unlock_irqrestore(&dev->event_lock, flags); | 665 | spin_unlock_irqrestore(&dev->event_lock, flags); |
| 666 | |||
| 667 | if (p->fence) | ||
| 668 | fence_put(p->fence); | ||
| 669 | |||
| 666 | kfree(p); | 670 | kfree(p); |
| 667 | } | 671 | } |
| 668 | EXPORT_SYMBOL(drm_event_cancel_free); | 672 | EXPORT_SYMBOL(drm_event_cancel_free); |
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 29c56b4331e0..cbb8b77c363c 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c | |||
| @@ -102,83 +102,105 @@ char *drm_get_format_name(uint32_t format) | |||
| 102 | } | 102 | } |
| 103 | EXPORT_SYMBOL(drm_get_format_name); | 103 | EXPORT_SYMBOL(drm_get_format_name); |
| 104 | 104 | ||
| 105 | /* | ||
| 106 | * Internal function to query information for a given format. See | ||
| 107 | * drm_format_info() for the public API. | ||
| 108 | */ | ||
| 109 | const struct drm_format_info *__drm_format_info(u32 format) | ||
| 110 | { | ||
| 111 | static const struct drm_format_info formats[] = { | ||
| 112 | { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 113 | { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 114 | { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 115 | { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 116 | { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 117 | { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 118 | { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 119 | { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 120 | { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 121 | { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 122 | { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 123 | { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 124 | { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 125 | { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 126 | { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 127 | { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 128 | { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 129 | { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 130 | { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 131 | { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 132 | { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 133 | { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 134 | { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 135 | { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 136 | { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 137 | { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 138 | { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 139 | { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 140 | { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 141 | { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 142 | { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 143 | { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 144 | { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 145 | { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 146 | { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 147 | { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 148 | { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 149 | { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 150 | { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 151 | { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 }, | ||
| 152 | { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 }, | ||
| 153 | { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 }, | ||
| 154 | { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 }, | ||
| 155 | { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 }, | ||
| 156 | { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 }, | ||
| 157 | { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 }, | ||
| 158 | { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 }, | ||
| 159 | { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 }, | ||
| 160 | { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 }, | ||
| 161 | { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 }, | ||
| 162 | { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 }, | ||
| 163 | { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 }, | ||
| 164 | { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 }, | ||
| 165 | { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 166 | { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 167 | { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, | ||
| 168 | { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, | ||
| 169 | { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, | ||
| 170 | { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, | ||
| 171 | { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | ||
| 172 | }; | ||
| 173 | |||
| 174 | unsigned int i; | ||
| 175 | |||
| 176 | for (i = 0; i < ARRAY_SIZE(formats); ++i) { | ||
| 177 | if (formats[i].format == format) | ||
| 178 | return &formats[i]; | ||
| 179 | } | ||
| 180 | |||
| 181 | return NULL; | ||
| 182 | } | ||
| 183 | |||
| 105 | /** | 184 | /** |
| 106 | * drm_fb_get_bpp_depth - get the bpp/depth values for format | 185 | * drm_format_info - query information for a given format |
| 107 | * @format: pixel format (DRM_FORMAT_*) | 186 | * @format: pixel format (DRM_FORMAT_*) |
| 108 | * @depth: storage for the depth value | ||
| 109 | * @bpp: storage for the bpp value | ||
| 110 | * | 187 | * |
| 111 | * This only supports RGB formats here for compat with code that doesn't use | 188 | * The caller should only pass a supported pixel format to this function. |
| 112 | * pixel formats directly yet. | 189 | * Unsupported pixel formats will generate a warning in the kernel log. |
| 190 | * | ||
| 191 | * Returns: | ||
| 192 | * The instance of struct drm_format_info that describes the pixel format, or | ||
| 193 | * NULL if the format is unsupported. | ||
| 113 | */ | 194 | */ |
| 114 | void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, | 195 | const struct drm_format_info *drm_format_info(u32 format) |
| 115 | int *bpp) | ||
| 116 | { | 196 | { |
| 117 | char *format_name; | 197 | const struct drm_format_info *info; |
| 118 | 198 | ||
| 119 | switch (format) { | 199 | info = __drm_format_info(format); |
| 120 | case DRM_FORMAT_C8: | 200 | WARN_ON(!info); |
| 121 | case DRM_FORMAT_RGB332: | 201 | return info; |
| 122 | case DRM_FORMAT_BGR233: | ||
| 123 | *depth = 8; | ||
| 124 | *bpp = 8; | ||
| 125 | break; | ||
| 126 | case DRM_FORMAT_XRGB1555: | ||
| 127 | case DRM_FORMAT_XBGR1555: | ||
| 128 | case DRM_FORMAT_RGBX5551: | ||
| 129 | case DRM_FORMAT_BGRX5551: | ||
| 130 | case DRM_FORMAT_ARGB1555: | ||
| 131 | case DRM_FORMAT_ABGR1555: | ||
| 132 | case DRM_FORMAT_RGBA5551: | ||
| 133 | case DRM_FORMAT_BGRA5551: | ||
| 134 | *depth = 15; | ||
| 135 | *bpp = 16; | ||
| 136 | break; | ||
| 137 | case DRM_FORMAT_RGB565: | ||
| 138 | case DRM_FORMAT_BGR565: | ||
| 139 | *depth = 16; | ||
| 140 | *bpp = 16; | ||
| 141 | break; | ||
| 142 | case DRM_FORMAT_RGB888: | ||
| 143 | case DRM_FORMAT_BGR888: | ||
| 144 | *depth = 24; | ||
| 145 | *bpp = 24; | ||
| 146 | break; | ||
| 147 | case DRM_FORMAT_XRGB8888: | ||
| 148 | case DRM_FORMAT_XBGR8888: | ||
| 149 | case DRM_FORMAT_RGBX8888: | ||
| 150 | case DRM_FORMAT_BGRX8888: | ||
| 151 | *depth = 24; | ||
| 152 | *bpp = 32; | ||
| 153 | break; | ||
| 154 | case DRM_FORMAT_XRGB2101010: | ||
| 155 | case DRM_FORMAT_XBGR2101010: | ||
| 156 | case DRM_FORMAT_RGBX1010102: | ||
| 157 | case DRM_FORMAT_BGRX1010102: | ||
| 158 | case DRM_FORMAT_ARGB2101010: | ||
| 159 | case DRM_FORMAT_ABGR2101010: | ||
| 160 | case DRM_FORMAT_RGBA1010102: | ||
| 161 | case DRM_FORMAT_BGRA1010102: | ||
| 162 | *depth = 30; | ||
| 163 | *bpp = 32; | ||
| 164 | break; | ||
| 165 | case DRM_FORMAT_ARGB8888: | ||
| 166 | case DRM_FORMAT_ABGR8888: | ||
| 167 | case DRM_FORMAT_RGBA8888: | ||
| 168 | case DRM_FORMAT_BGRA8888: | ||
| 169 | *depth = 32; | ||
| 170 | *bpp = 32; | ||
| 171 | break; | ||
| 172 | default: | ||
| 173 | format_name = drm_get_format_name(format); | ||
| 174 | DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name); | ||
| 175 | kfree(format_name); | ||
| 176 | *depth = 0; | ||
| 177 | *bpp = 0; | ||
| 178 | break; | ||
| 179 | } | ||
| 180 | } | 202 | } |
| 181 | EXPORT_SYMBOL(drm_fb_get_bpp_depth); | 203 | EXPORT_SYMBOL(drm_format_info); |
| 182 | 204 | ||
| 183 | /** | 205 | /** |
| 184 | * drm_format_num_planes - get the number of planes for format | 206 | * drm_format_num_planes - get the number of planes for format |
| @@ -189,28 +211,10 @@ EXPORT_SYMBOL(drm_fb_get_bpp_depth); | |||
| 189 | */ | 211 | */ |
| 190 | int drm_format_num_planes(uint32_t format) | 212 | int drm_format_num_planes(uint32_t format) |
| 191 | { | 213 | { |
| 192 | switch (format) { | 214 | const struct drm_format_info *info; |
| 193 | case DRM_FORMAT_YUV410: | 215 | |
| 194 | case DRM_FORMAT_YVU410: | 216 | info = drm_format_info(format); |
| 195 | case DRM_FORMAT_YUV411: | 217 | return info ? info->num_planes : 1; |
| 196 | case DRM_FORMAT_YVU411: | ||
| 197 | case DRM_FORMAT_YUV420: | ||
| 198 | case DRM_FORMAT_YVU420: | ||
| 199 | case DRM_FORMAT_YUV422: | ||
| 200 | case DRM_FORMAT_YVU422: | ||
| 201 | case DRM_FORMAT_YUV444: | ||
| 202 | case DRM_FORMAT_YVU444: | ||
| 203 | return 3; | ||
| 204 | case DRM_FORMAT_NV12: | ||
| 205 | case DRM_FORMAT_NV21: | ||
| 206 | case DRM_FORMAT_NV16: | ||
| 207 | case DRM_FORMAT_NV61: | ||
| 208 | case DRM_FORMAT_NV24: | ||
| 209 | case DRM_FORMAT_NV42: | ||
| 210 | return 2; | ||
| 211 | default: | ||
| 212 | return 1; | ||
| 213 | } | ||
| 214 | } | 218 | } |
| 215 | EXPORT_SYMBOL(drm_format_num_planes); | 219 | EXPORT_SYMBOL(drm_format_num_planes); |
| 216 | 220 | ||
| @@ -224,40 +228,13 @@ EXPORT_SYMBOL(drm_format_num_planes); | |||
| 224 | */ | 228 | */ |
| 225 | int drm_format_plane_cpp(uint32_t format, int plane) | 229 | int drm_format_plane_cpp(uint32_t format, int plane) |
| 226 | { | 230 | { |
| 227 | unsigned int depth; | 231 | const struct drm_format_info *info; |
| 228 | int bpp; | ||
| 229 | 232 | ||
| 230 | if (plane >= drm_format_num_planes(format)) | 233 | info = drm_format_info(format); |
| 234 | if (!info || plane >= info->num_planes) | ||
| 231 | return 0; | 235 | return 0; |
| 232 | 236 | ||
| 233 | switch (format) { | 237 | return info->cpp[plane]; |
| 234 | case DRM_FORMAT_YUYV: | ||
| 235 | case DRM_FORMAT_YVYU: | ||
| 236 | case DRM_FORMAT_UYVY: | ||
| 237 | case DRM_FORMAT_VYUY: | ||
| 238 | return 2; | ||
| 239 | case DRM_FORMAT_NV12: | ||
| 240 | case DRM_FORMAT_NV21: | ||
| 241 | case DRM_FORMAT_NV16: | ||
| 242 | case DRM_FORMAT_NV61: | ||
| 243 | case DRM_FORMAT_NV24: | ||
| 244 | case DRM_FORMAT_NV42: | ||
| 245 | return plane ? 2 : 1; | ||
| 246 | case DRM_FORMAT_YUV410: | ||
| 247 | case DRM_FORMAT_YVU410: | ||
| 248 | case DRM_FORMAT_YUV411: | ||
| 249 | case DRM_FORMAT_YVU411: | ||
| 250 | case DRM_FORMAT_YUV420: | ||
| 251 | case DRM_FORMAT_YVU420: | ||
| 252 | case DRM_FORMAT_YUV422: | ||
| 253 | case DRM_FORMAT_YVU422: | ||
| 254 | case DRM_FORMAT_YUV444: | ||
| 255 | case DRM_FORMAT_YVU444: | ||
| 256 | return 1; | ||
| 257 | default: | ||
| 258 | drm_fb_get_bpp_depth(format, &depth, &bpp); | ||
| 259 | return bpp >> 3; | ||
| 260 | } | ||
| 261 | } | 238 | } |
| 262 | EXPORT_SYMBOL(drm_format_plane_cpp); | 239 | EXPORT_SYMBOL(drm_format_plane_cpp); |
| 263 | 240 | ||
| @@ -271,28 +248,10 @@ EXPORT_SYMBOL(drm_format_plane_cpp); | |||
| 271 | */ | 248 | */ |
| 272 | int drm_format_horz_chroma_subsampling(uint32_t format) | 249 | int drm_format_horz_chroma_subsampling(uint32_t format) |
| 273 | { | 250 | { |
| 274 | switch (format) { | 251 | const struct drm_format_info *info; |
| 275 | case DRM_FORMAT_YUV411: | 252 | |
| 276 | case DRM_FORMAT_YVU411: | 253 | info = drm_format_info(format); |
| 277 | case DRM_FORMAT_YUV410: | 254 | return info ? info->hsub : 1; |
| 278 | case DRM_FORMAT_YVU410: | ||
| 279 | return 4; | ||
| 280 | case DRM_FORMAT_YUYV: | ||
| 281 | case DRM_FORMAT_YVYU: | ||
| 282 | case DRM_FORMAT_UYVY: | ||
| 283 | case DRM_FORMAT_VYUY: | ||
| 284 | case DRM_FORMAT_NV12: | ||
| 285 | case DRM_FORMAT_NV21: | ||
| 286 | case DRM_FORMAT_NV16: | ||
| 287 | case DRM_FORMAT_NV61: | ||
| 288 | case DRM_FORMAT_YUV422: | ||
| 289 | case DRM_FORMAT_YVU422: | ||
| 290 | case DRM_FORMAT_YUV420: | ||
| 291 | case DRM_FORMAT_YVU420: | ||
| 292 | return 2; | ||
| 293 | default: | ||
| 294 | return 1; | ||
| 295 | } | ||
| 296 | } | 255 | } |
| 297 | EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); | 256 | EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); |
| 298 | 257 | ||
| @@ -306,18 +265,10 @@ EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); | |||
| 306 | */ | 265 | */ |
| 307 | int drm_format_vert_chroma_subsampling(uint32_t format) | 266 | int drm_format_vert_chroma_subsampling(uint32_t format) |
| 308 | { | 267 | { |
| 309 | switch (format) { | 268 | const struct drm_format_info *info; |
| 310 | case DRM_FORMAT_YUV410: | 269 | |
| 311 | case DRM_FORMAT_YVU410: | 270 | info = drm_format_info(format); |
| 312 | return 4; | 271 | return info ? info->vsub : 1; |
| 313 | case DRM_FORMAT_YUV420: | ||
| 314 | case DRM_FORMAT_YVU420: | ||
| 315 | case DRM_FORMAT_NV12: | ||
| 316 | case DRM_FORMAT_NV21: | ||
| 317 | return 2; | ||
| 318 | default: | ||
| 319 | return 1; | ||
| 320 | } | ||
| 321 | } | 272 | } |
| 322 | EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); | 273 | EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); |
| 323 | 274 | ||
| @@ -332,13 +283,16 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); | |||
| 332 | */ | 283 | */ |
| 333 | int drm_format_plane_width(int width, uint32_t format, int plane) | 284 | int drm_format_plane_width(int width, uint32_t format, int plane) |
| 334 | { | 285 | { |
| 335 | if (plane >= drm_format_num_planes(format)) | 286 | const struct drm_format_info *info; |
| 287 | |||
| 288 | info = drm_format_info(format); | ||
| 289 | if (!info || plane >= info->num_planes) | ||
| 336 | return 0; | 290 | return 0; |
| 337 | 291 | ||
| 338 | if (plane == 0) | 292 | if (plane == 0) |
| 339 | return width; | 293 | return width; |
| 340 | 294 | ||
| 341 | return width / drm_format_horz_chroma_subsampling(format); | 295 | return width / info->hsub; |
| 342 | } | 296 | } |
| 343 | EXPORT_SYMBOL(drm_format_plane_width); | 297 | EXPORT_SYMBOL(drm_format_plane_width); |
| 344 | 298 | ||
| @@ -353,12 +307,15 @@ EXPORT_SYMBOL(drm_format_plane_width); | |||
| 353 | */ | 307 | */ |
| 354 | int drm_format_plane_height(int height, uint32_t format, int plane) | 308 | int drm_format_plane_height(int height, uint32_t format, int plane) |
| 355 | { | 309 | { |
| 356 | if (plane >= drm_format_num_planes(format)) | 310 | const struct drm_format_info *info; |
| 311 | |||
| 312 | info = drm_format_info(format); | ||
| 313 | if (!info || plane >= info->num_planes) | ||
| 357 | return 0; | 314 | return 0; |
| 358 | 315 | ||
| 359 | if (plane == 0) | 316 | if (plane == 0) |
| 360 | return height; | 317 | return height; |
| 361 | 318 | ||
| 362 | return height / drm_format_vert_chroma_subsampling(format); | 319 | return height / info->vsub; |
| 363 | } | 320 | } |
| 364 | EXPORT_SYMBOL(drm_format_plane_height); | 321 | EXPORT_SYMBOL(drm_format_plane_height); |
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 398efd67cb93..49fd7db758e0 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c | |||
| @@ -126,111 +126,33 @@ int drm_mode_addfb(struct drm_device *dev, | |||
| 126 | return 0; | 126 | return 0; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | static int format_check(const struct drm_mode_fb_cmd2 *r) | ||
| 130 | { | ||
| 131 | uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; | ||
| 132 | char *format_name; | ||
| 133 | |||
| 134 | switch (format) { | ||
| 135 | case DRM_FORMAT_C8: | ||
| 136 | case DRM_FORMAT_RGB332: | ||
| 137 | case DRM_FORMAT_BGR233: | ||
| 138 | case DRM_FORMAT_XRGB4444: | ||
| 139 | case DRM_FORMAT_XBGR4444: | ||
| 140 | case DRM_FORMAT_RGBX4444: | ||
| 141 | case DRM_FORMAT_BGRX4444: | ||
| 142 | case DRM_FORMAT_ARGB4444: | ||
| 143 | case DRM_FORMAT_ABGR4444: | ||
| 144 | case DRM_FORMAT_RGBA4444: | ||
| 145 | case DRM_FORMAT_BGRA4444: | ||
| 146 | case DRM_FORMAT_XRGB1555: | ||
| 147 | case DRM_FORMAT_XBGR1555: | ||
| 148 | case DRM_FORMAT_RGBX5551: | ||
| 149 | case DRM_FORMAT_BGRX5551: | ||
| 150 | case DRM_FORMAT_ARGB1555: | ||
| 151 | case DRM_FORMAT_ABGR1555: | ||
| 152 | case DRM_FORMAT_RGBA5551: | ||
| 153 | case DRM_FORMAT_BGRA5551: | ||
| 154 | case DRM_FORMAT_RGB565: | ||
| 155 | case DRM_FORMAT_BGR565: | ||
| 156 | case DRM_FORMAT_RGB888: | ||
| 157 | case DRM_FORMAT_BGR888: | ||
| 158 | case DRM_FORMAT_XRGB8888: | ||
| 159 | case DRM_FORMAT_XBGR8888: | ||
| 160 | case DRM_FORMAT_RGBX8888: | ||
| 161 | case DRM_FORMAT_BGRX8888: | ||
| 162 | case DRM_FORMAT_ARGB8888: | ||
| 163 | case DRM_FORMAT_ABGR8888: | ||
| 164 | case DRM_FORMAT_RGBA8888: | ||
| 165 | case DRM_FORMAT_BGRA8888: | ||
| 166 | case DRM_FORMAT_XRGB2101010: | ||
| 167 | case DRM_FORMAT_XBGR2101010: | ||
| 168 | case DRM_FORMAT_RGBX1010102: | ||
| 169 | case DRM_FORMAT_BGRX1010102: | ||
| 170 | case DRM_FORMAT_ARGB2101010: | ||
| 171 | case DRM_FORMAT_ABGR2101010: | ||
| 172 | case DRM_FORMAT_RGBA1010102: | ||
| 173 | case DRM_FORMAT_BGRA1010102: | ||
| 174 | case DRM_FORMAT_YUYV: | ||
| 175 | case DRM_FORMAT_YVYU: | ||
| 176 | case DRM_FORMAT_UYVY: | ||
| 177 | case DRM_FORMAT_VYUY: | ||
| 178 | case DRM_FORMAT_AYUV: | ||
| 179 | case DRM_FORMAT_NV12: | ||
| 180 | case DRM_FORMAT_NV21: | ||
| 181 | case DRM_FORMAT_NV16: | ||
| 182 | case DRM_FORMAT_NV61: | ||
| 183 | case DRM_FORMAT_NV24: | ||
| 184 | case DRM_FORMAT_NV42: | ||
| 185 | case DRM_FORMAT_YUV410: | ||
| 186 | case DRM_FORMAT_YVU410: | ||
| 187 | case DRM_FORMAT_YUV411: | ||
| 188 | case DRM_FORMAT_YVU411: | ||
| 189 | case DRM_FORMAT_YUV420: | ||
| 190 | case DRM_FORMAT_YVU420: | ||
| 191 | case DRM_FORMAT_YUV422: | ||
| 192 | case DRM_FORMAT_YVU422: | ||
| 193 | case DRM_FORMAT_YUV444: | ||
| 194 | case DRM_FORMAT_YVU444: | ||
| 195 | return 0; | ||
| 196 | default: | ||
| 197 | format_name = drm_get_format_name(r->pixel_format); | ||
| 198 | DRM_DEBUG_KMS("invalid pixel format %s\n", format_name); | ||
| 199 | kfree(format_name); | ||
| 200 | return -EINVAL; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | 129 | static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) |
| 205 | { | 130 | { |
| 206 | int ret, hsub, vsub, num_planes, i; | 131 | const struct drm_format_info *info; |
| 132 | int i; | ||
| 207 | 133 | ||
| 208 | ret = format_check(r); | 134 | info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); |
| 209 | if (ret) { | 135 | if (!info) { |
| 210 | char *format_name = drm_get_format_name(r->pixel_format); | 136 | char *format_name = drm_get_format_name(r->pixel_format); |
| 211 | DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name); | 137 | DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name); |
| 212 | kfree(format_name); | 138 | kfree(format_name); |
| 213 | return ret; | 139 | return -EINVAL; |
| 214 | } | 140 | } |
| 215 | 141 | ||
| 216 | hsub = drm_format_horz_chroma_subsampling(r->pixel_format); | 142 | if (r->width == 0 || r->width % info->hsub) { |
| 217 | vsub = drm_format_vert_chroma_subsampling(r->pixel_format); | ||
| 218 | num_planes = drm_format_num_planes(r->pixel_format); | ||
| 219 | |||
| 220 | if (r->width == 0 || r->width % hsub) { | ||
| 221 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); | 143 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); |
| 222 | return -EINVAL; | 144 | return -EINVAL; |
| 223 | } | 145 | } |
| 224 | 146 | ||
| 225 | if (r->height == 0 || r->height % vsub) { | 147 | if (r->height == 0 || r->height % info->vsub) { |
| 226 | DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); | 148 | DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); |
| 227 | return -EINVAL; | 149 | return -EINVAL; |
| 228 | } | 150 | } |
| 229 | 151 | ||
| 230 | for (i = 0; i < num_planes; i++) { | 152 | for (i = 0; i < info->num_planes; i++) { |
| 231 | unsigned int width = r->width / (i != 0 ? hsub : 1); | 153 | unsigned int width = r->width / (i != 0 ? info->hsub : 1); |
| 232 | unsigned int height = r->height / (i != 0 ? vsub : 1); | 154 | unsigned int height = r->height / (i != 0 ? info->vsub : 1); |
| 233 | unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i); | 155 | unsigned int cpp = info->cpp[i]; |
| 234 | 156 | ||
| 235 | if (!r->handles[i]) { | 157 | if (!r->handles[i]) { |
| 236 | DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); | 158 | DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); |
| @@ -273,7 +195,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | |||
| 273 | } | 195 | } |
| 274 | } | 196 | } |
| 275 | 197 | ||
| 276 | for (i = num_planes; i < 4; i++) { | 198 | for (i = info->num_planes; i < 4; i++) { |
| 277 | if (r->modifier[i]) { | 199 | if (r->modifier[i]) { |
| 278 | DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i); | 200 | DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i); |
| 279 | return -EINVAL; | 201 | return -EINVAL; |
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index e66af289a016..abd209863ef4 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h | |||
| @@ -100,6 +100,9 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, | |||
| 100 | int drm_debugfs_cleanup(struct drm_minor *minor); | 100 | int drm_debugfs_cleanup(struct drm_minor *minor); |
| 101 | int drm_debugfs_connector_add(struct drm_connector *connector); | 101 | int drm_debugfs_connector_add(struct drm_connector *connector); |
| 102 | void drm_debugfs_connector_remove(struct drm_connector *connector); | 102 | void drm_debugfs_connector_remove(struct drm_connector *connector); |
| 103 | int drm_debugfs_crtc_add(struct drm_crtc *crtc); | ||
| 104 | void drm_debugfs_crtc_remove(struct drm_crtc *crtc); | ||
| 105 | int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc); | ||
| 103 | #else | 106 | #else |
| 104 | static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, | 107 | static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, |
| 105 | struct dentry *root) | 108 | struct dentry *root) |
| @@ -119,4 +122,17 @@ static inline int drm_debugfs_connector_add(struct drm_connector *connector) | |||
| 119 | static inline void drm_debugfs_connector_remove(struct drm_connector *connector) | 122 | static inline void drm_debugfs_connector_remove(struct drm_connector *connector) |
| 120 | { | 123 | { |
| 121 | } | 124 | } |
| 125 | |||
| 126 | static inline int drm_debugfs_crtc_add(struct drm_crtc *crtc) | ||
| 127 | { | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | static inline void drm_debugfs_crtc_remove(struct drm_crtc *crtc) | ||
| 131 | { | ||
| 132 | } | ||
| 133 | |||
| 134 | static inline int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) | ||
| 135 | { | ||
| 136 | return 0; | ||
| 137 | } | ||
| 122 | #endif | 138 | #endif |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index b969a64a1514..48a6167f5e7b 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -952,8 +952,10 @@ static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, | |||
| 952 | u32 vblank_count; | 952 | u32 vblank_count; |
| 953 | unsigned int seq; | 953 | unsigned int seq; |
| 954 | 954 | ||
| 955 | if (WARN_ON(pipe >= dev->num_crtcs)) | 955 | if (WARN_ON(pipe >= dev->num_crtcs)) { |
| 956 | *vblanktime = (struct timeval) { 0 }; | ||
| 956 | return 0; | 957 | return 0; |
| 958 | } | ||
| 957 | 959 | ||
| 958 | do { | 960 | do { |
| 959 | seq = read_seqbegin(&vblank->seqlock); | 961 | seq = read_seqbegin(&vblank->seqlock); |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 53f07ac7c174..f64ac86deb84 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
| @@ -165,6 +165,7 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, | |||
| 165 | unsigned int vfieldrate, hperiod; | 165 | unsigned int vfieldrate, hperiod; |
| 166 | int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; | 166 | int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; |
| 167 | int interlace; | 167 | int interlace; |
| 168 | u64 tmp; | ||
| 168 | 169 | ||
| 169 | /* allocate the drm_display_mode structure. If failure, we will | 170 | /* allocate the drm_display_mode structure. If failure, we will |
| 170 | * return directly | 171 | * return directly |
| @@ -322,8 +323,11 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, | |||
| 322 | drm_mode->vsync_end = drm_mode->vsync_start + vsync; | 323 | drm_mode->vsync_end = drm_mode->vsync_start + vsync; |
| 323 | } | 324 | } |
| 324 | /* 15/13. Find pixel clock frequency (kHz for xf86) */ | 325 | /* 15/13. Find pixel clock frequency (kHz for xf86) */ |
| 325 | drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod; | 326 | tmp = drm_mode->htotal; /* perform intermediate calcs in u64 */ |
| 326 | drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP; | 327 | tmp *= HV_FACTOR * 1000; |
| 328 | do_div(tmp, hperiod); | ||
| 329 | tmp -= drm_mode->clock % CVT_CLOCK_STEP; | ||
| 330 | drm_mode->clock = tmp; | ||
| 327 | /* 18/16. Find actual vertical frame frequency */ | 331 | /* 18/16. Find actual vertical frame frequency */ |
| 328 | /* ignore - just set the mode flag for interlaced */ | 332 | /* ignore - just set the mode flag for interlaced */ |
| 329 | if (interlaced) { | 333 | if (interlaced) { |
| @@ -997,6 +1001,7 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, | |||
| 997 | mode1->vsync_end == mode2->vsync_end && | 1001 | mode1->vsync_end == mode2->vsync_end && |
| 998 | mode1->vtotal == mode2->vtotal && | 1002 | mode1->vtotal == mode2->vtotal && |
| 999 | mode1->vscan == mode2->vscan && | 1003 | mode1->vscan == mode2->vscan && |
| 1004 | mode1->picture_aspect_ratio == mode2->picture_aspect_ratio && | ||
| 1000 | (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) == | 1005 | (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) == |
| 1001 | (mode2->flags & ~DRM_MODE_FLAG_3D_MASK)) | 1006 | (mode2->flags & ~DRM_MODE_FLAG_3D_MASK)) |
| 1002 | return true; | 1007 | return true; |
| @@ -1499,6 +1504,27 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, | |||
| 1499 | out->vrefresh = in->vrefresh; | 1504 | out->vrefresh = in->vrefresh; |
| 1500 | out->flags = in->flags; | 1505 | out->flags = in->flags; |
| 1501 | out->type = in->type; | 1506 | out->type = in->type; |
| 1507 | out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK; | ||
| 1508 | |||
| 1509 | switch (in->picture_aspect_ratio) { | ||
| 1510 | case HDMI_PICTURE_ASPECT_4_3: | ||
| 1511 | out->flags |= DRM_MODE_FLAG_PIC_AR_4_3; | ||
| 1512 | break; | ||
| 1513 | case HDMI_PICTURE_ASPECT_16_9: | ||
| 1514 | out->flags |= DRM_MODE_FLAG_PIC_AR_16_9; | ||
| 1515 | break; | ||
| 1516 | case HDMI_PICTURE_ASPECT_64_27: | ||
| 1517 | out->flags |= DRM_MODE_FLAG_PIC_AR_64_27; | ||
| 1518 | break; | ||
| 1519 | case DRM_MODE_PICTURE_ASPECT_256_135: | ||
| 1520 | out->flags |= DRM_MODE_FLAG_PIC_AR_256_135; | ||
| 1521 | break; | ||
| 1522 | case HDMI_PICTURE_ASPECT_RESERVED: | ||
| 1523 | default: | ||
| 1524 | out->flags |= DRM_MODE_FLAG_PIC_AR_NONE; | ||
| 1525 | break; | ||
| 1526 | } | ||
| 1527 | |||
| 1502 | strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); | 1528 | strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); |
| 1503 | out->name[DRM_DISPLAY_MODE_LEN-1] = 0; | 1529 | out->name[DRM_DISPLAY_MODE_LEN-1] = 0; |
| 1504 | } | 1530 | } |
| @@ -1544,6 +1570,27 @@ int drm_mode_convert_umode(struct drm_display_mode *out, | |||
| 1544 | strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); | 1570 | strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); |
| 1545 | out->name[DRM_DISPLAY_MODE_LEN-1] = 0; | 1571 | out->name[DRM_DISPLAY_MODE_LEN-1] = 0; |
| 1546 | 1572 | ||
| 1573 | /* Clearing picture aspect ratio bits from out flags */ | ||
| 1574 | out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK; | ||
| 1575 | |||
| 1576 | switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) { | ||
| 1577 | case DRM_MODE_FLAG_PIC_AR_4_3: | ||
| 1578 | out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_4_3; | ||
| 1579 | break; | ||
| 1580 | case DRM_MODE_FLAG_PIC_AR_16_9: | ||
| 1581 | out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_16_9; | ||
| 1582 | break; | ||
| 1583 | case DRM_MODE_FLAG_PIC_AR_64_27: | ||
| 1584 | out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_64_27; | ||
| 1585 | break; | ||
| 1586 | case DRM_MODE_FLAG_PIC_AR_256_135: | ||
| 1587 | out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_256_135; | ||
| 1588 | break; | ||
| 1589 | default: | ||
| 1590 | out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE; | ||
| 1591 | break; | ||
| 1592 | } | ||
| 1593 | |||
| 1547 | out->status = drm_mode_validate_basic(out); | 1594 | out->status = drm_mode_validate_basic(out); |
| 1548 | if (out->status != MODE_OK) | 1595 | if (out->status != MODE_OK) |
| 1549 | goto out; | 1596 | goto out; |
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 1d45738f8f98..2544dfe7354c 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c | |||
| @@ -70,8 +70,23 @@ EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); | |||
| 70 | void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | 70 | void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, |
| 71 | const struct drm_mode_fb_cmd2 *mode_cmd) | 71 | const struct drm_mode_fb_cmd2 *mode_cmd) |
| 72 | { | 72 | { |
| 73 | const struct drm_format_info *info; | ||
| 73 | int i; | 74 | int i; |
| 74 | 75 | ||
| 76 | info = drm_format_info(mode_cmd->pixel_format); | ||
| 77 | if (!info || !info->depth) { | ||
| 78 | char *format_name = drm_get_format_name(mode_cmd->pixel_format); | ||
| 79 | |||
| 80 | DRM_DEBUG_KMS("non-RGB pixel format %s\n", format_name); | ||
| 81 | kfree(format_name); | ||
| 82 | |||
| 83 | fb->depth = 0; | ||
| 84 | fb->bits_per_pixel = 0; | ||
| 85 | } else { | ||
| 86 | fb->depth = info->depth; | ||
| 87 | fb->bits_per_pixel = info->cpp[0] * 8; | ||
| 88 | } | ||
| 89 | |||
| 75 | fb->width = mode_cmd->width; | 90 | fb->width = mode_cmd->width; |
| 76 | fb->height = mode_cmd->height; | 91 | fb->height = mode_cmd->height; |
| 77 | for (i = 0; i < 4; i++) { | 92 | for (i = 0; i < 4; i++) { |
| @@ -79,8 +94,6 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | |||
| 79 | fb->offsets[i] = mode_cmd->offsets[i]; | 94 | fb->offsets[i] = mode_cmd->offsets[i]; |
| 80 | fb->modifier[i] = mode_cmd->modifier[i]; | 95 | fb->modifier[i] = mode_cmd->modifier[i]; |
| 81 | } | 96 | } |
| 82 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, | ||
| 83 | &fb->bits_per_pixel); | ||
| 84 | fb->pixel_format = mode_cmd->pixel_format; | 97 | fb->pixel_format = mode_cmd->pixel_format; |
| 85 | fb->flags = mode_cmd->flags; | 98 | fb->flags = mode_cmd->flags; |
| 86 | } | 99 | } |
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 0370b842d9cc..3755ef935af4 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c | |||
| @@ -409,20 +409,16 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, | |||
| 409 | struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); | 409 | struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); |
| 410 | struct drm_device *dev = obj->dev; | 410 | struct drm_device *dev = obj->dev; |
| 411 | bool write = !!(op & ETNA_PREP_WRITE); | 411 | bool write = !!(op & ETNA_PREP_WRITE); |
| 412 | int ret; | 412 | unsigned long remain = |
| 413 | 413 | op & ETNA_PREP_NOSYNC ? 0 : etnaviv_timeout_to_jiffies(timeout); | |
| 414 | if (op & ETNA_PREP_NOSYNC) { | 414 | long lret; |
| 415 | if (!reservation_object_test_signaled_rcu(etnaviv_obj->resv, | 415 | |
| 416 | write)) | 416 | lret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv, |
| 417 | return -EBUSY; | 417 | write, true, remain); |
| 418 | } else { | 418 | if (lret < 0) |
| 419 | unsigned long remain = etnaviv_timeout_to_jiffies(timeout); | 419 | return lret; |
| 420 | 420 | else if (lret == 0) | |
| 421 | ret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv, | 421 | return remain == 0 ? -EBUSY : -ETIMEDOUT; |
| 422 | write, true, remain); | ||
| 423 | if (ret <= 0) | ||
| 424 | return ret == 0 ? -ETIMEDOUT : ret; | ||
| 425 | } | ||
| 426 | 422 | ||
| 427 | if (etnaviv_obj->flags & ETNA_BO_CACHED) { | 423 | if (etnaviv_obj->flags & ETNA_BO_CACHED) { |
| 428 | if (!etnaviv_obj->sgt) { | 424 | if (!etnaviv_obj->sgt) { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index def78c8c1780..4a21a745c373 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
| @@ -69,7 +69,7 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit) | |||
| 69 | 69 | ||
| 70 | drm_atomic_helper_cleanup_planes(dev, state); | 70 | drm_atomic_helper_cleanup_planes(dev, state); |
| 71 | 71 | ||
| 72 | drm_atomic_state_free(state); | 72 | drm_atomic_state_put(state); |
| 73 | 73 | ||
| 74 | spin_lock(&priv->lock); | 74 | spin_lock(&priv->lock); |
| 75 | priv->pending &= ~commit->crtcs; | 75 | priv->pending &= ~commit->crtcs; |
| @@ -254,6 +254,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, | |||
| 254 | 254 | ||
| 255 | drm_atomic_helper_swap_state(state, true); | 255 | drm_atomic_helper_swap_state(state, true); |
| 256 | 256 | ||
| 257 | drm_atomic_state_get(state); | ||
| 257 | if (nonblock) | 258 | if (nonblock) |
| 258 | schedule_work(&commit->work); | 259 | schedule_work(&commit->work); |
| 259 | else | 260 | else |
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 3a44e705db53..97daf23f3fef 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c | |||
| @@ -124,7 +124,7 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 124 | unsigned long phys_addr = (unsigned long)dev_priv->stolen_base + | 124 | unsigned long phys_addr = (unsigned long)dev_priv->stolen_base + |
| 125 | psbfb->gtt->offset; | 125 | psbfb->gtt->offset; |
| 126 | 126 | ||
| 127 | page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | 127 | page_num = vma_pages(vma); |
| 128 | address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT); | 128 | address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT); |
| 129 | 129 | ||
| 130 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 130 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| @@ -236,22 +236,20 @@ static int psb_framebuffer_init(struct drm_device *dev, | |||
| 236 | const struct drm_mode_fb_cmd2 *mode_cmd, | 236 | const struct drm_mode_fb_cmd2 *mode_cmd, |
| 237 | struct gtt_range *gt) | 237 | struct gtt_range *gt) |
| 238 | { | 238 | { |
| 239 | u32 bpp, depth; | 239 | const struct drm_format_info *info; |
| 240 | int ret; | 240 | int ret; |
| 241 | 241 | ||
| 242 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); | 242 | /* |
| 243 | * Reject unknown formats, YUV formats, and formats with more than | ||
| 244 | * 4 bytes per pixel. | ||
| 245 | */ | ||
| 246 | info = drm_format_info(mode_cmd->pixel_format); | ||
| 247 | if (!info || !info->depth || info->cpp[0] > 4) | ||
| 248 | return -EINVAL; | ||
| 243 | 249 | ||
| 244 | if (mode_cmd->pitches[0] & 63) | 250 | if (mode_cmd->pitches[0] & 63) |
| 245 | return -EINVAL; | 251 | return -EINVAL; |
| 246 | switch (bpp) { | 252 | |
| 247 | case 8: | ||
| 248 | case 16: | ||
| 249 | case 24: | ||
| 250 | case 32: | ||
| 251 | break; | ||
| 252 | default: | ||
| 253 | return -EINVAL; | ||
| 254 | } | ||
| 255 | drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); | 253 | drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); |
| 256 | fb->gtt = gt; | 254 | fb->gtt = gt; |
| 257 | ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); | 255 | ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); |
| @@ -298,7 +296,6 @@ static struct drm_framebuffer *psb_framebuffer_create | |||
| 298 | * psbfb_alloc - allocate frame buffer memory | 296 | * psbfb_alloc - allocate frame buffer memory |
| 299 | * @dev: the DRM device | 297 | * @dev: the DRM device |
| 300 | * @aligned_size: space needed | 298 | * @aligned_size: space needed |
| 301 | * @force: fall back to GEM buffers if need be | ||
| 302 | * | 299 | * |
| 303 | * Allocate the frame buffer. In the usual case we get a GTT range that | 300 | * Allocate the frame buffer. In the usual case we get a GTT range that |
| 304 | * is stolen memory backed and life is simple. If there isn't sufficient | 301 | * is stolen memory backed and life is simple. If there isn't sufficient |
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 8f69225ce2b4..76aea2e7fb9d 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c | |||
| @@ -76,6 +76,7 @@ static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) | |||
| 76 | * psb_gtt_insert - put an object into the GTT | 76 | * psb_gtt_insert - put an object into the GTT |
| 77 | * @dev: our DRM device | 77 | * @dev: our DRM device |
| 78 | * @r: our GTT range | 78 | * @r: our GTT range |
| 79 | * @resume: on resume | ||
| 79 | * | 80 | * |
| 80 | * Take our preallocated GTT range and insert the GEM object into | 81 | * Take our preallocated GTT range and insert the GEM object into |
| 81 | * the GTT. This is protected via the gtt mutex which the caller | 82 | * the GTT. This is protected via the gtt mutex which the caller |
| @@ -321,6 +322,7 @@ out: | |||
| 321 | * @len: length (bytes) of address space required | 322 | * @len: length (bytes) of address space required |
| 322 | * @name: resource name | 323 | * @name: resource name |
| 323 | * @backed: resource should be backed by stolen pages | 324 | * @backed: resource should be backed by stolen pages |
| 325 | * @align: requested alignment | ||
| 324 | * | 326 | * |
| 325 | * Ask the kernel core to find us a suitable range of addresses | 327 | * Ask the kernel core to find us a suitable range of addresses |
| 326 | * to use for a GTT mapping. | 328 | * to use for a GTT mapping. |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 27b0e34dadec..6c7bb87f764e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
| @@ -3941,10 +3941,9 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv, | |||
| 3941 | 3941 | ||
| 3942 | ret = drm_atomic_commit(state); | 3942 | ret = drm_atomic_commit(state); |
| 3943 | out: | 3943 | out: |
| 3944 | drm_modeset_unlock_all(dev); | ||
| 3945 | WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret); | 3944 | WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret); |
| 3946 | if (ret) | 3945 | drm_modeset_unlock_all(dev); |
| 3947 | drm_atomic_state_free(state); | 3946 | drm_atomic_state_put(state); |
| 3948 | } | 3947 | } |
| 3949 | 3948 | ||
| 3950 | static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, | 3949 | static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, |
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index b82de3072d4f..c762ae549a1c 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c | |||
| @@ -142,8 +142,9 @@ static int intel_plane_atomic_check(struct drm_plane *plane, | |||
| 142 | intel_state->clip.y2 = | 142 | intel_state->clip.y2 = |
| 143 | crtc_state->base.enable ? crtc_state->pipe_src_h : 0; | 143 | crtc_state->base.enable ? crtc_state->pipe_src_h : 0; |
| 144 | 144 | ||
| 145 | if (state->fb && intel_rotation_90_or_270(state->rotation)) { | 145 | if (state->fb && drm_rotation_90_or_270(state->rotation)) { |
| 146 | char *format_name; | 146 | char *format_name; |
| 147 | |||
| 147 | if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || | 148 | if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || |
| 148 | state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { | 149 | state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { |
| 149 | DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); | 150 | DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fbcfed63a76e..4c21d2ec2c51 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -2139,7 +2139,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, | |||
| 2139 | const struct drm_framebuffer *fb, | 2139 | const struct drm_framebuffer *fb, |
| 2140 | unsigned int rotation) | 2140 | unsigned int rotation) |
| 2141 | { | 2141 | { |
| 2142 | if (intel_rotation_90_or_270(rotation)) { | 2142 | if (drm_rotation_90_or_270(rotation)) { |
| 2143 | *view = i915_ggtt_view_rotated; | 2143 | *view = i915_ggtt_view_rotated; |
| 2144 | view->params.rotated = to_intel_framebuffer(fb)->rot_info; | 2144 | view->params.rotated = to_intel_framebuffer(fb)->rot_info; |
| 2145 | } else { | 2145 | } else { |
| @@ -2260,7 +2260,7 @@ void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) | |||
| 2260 | static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane, | 2260 | static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane, |
| 2261 | unsigned int rotation) | 2261 | unsigned int rotation) |
| 2262 | { | 2262 | { |
| 2263 | if (intel_rotation_90_or_270(rotation)) | 2263 | if (drm_rotation_90_or_270(rotation)) |
| 2264 | return to_intel_framebuffer(fb)->rotated[plane].pitch; | 2264 | return to_intel_framebuffer(fb)->rotated[plane].pitch; |
| 2265 | else | 2265 | else |
| 2266 | return fb->pitches[plane]; | 2266 | return fb->pitches[plane]; |
| @@ -2296,7 +2296,7 @@ void intel_add_fb_offsets(int *x, int *y, | |||
| 2296 | const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb); | 2296 | const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb); |
| 2297 | unsigned int rotation = state->base.rotation; | 2297 | unsigned int rotation = state->base.rotation; |
| 2298 | 2298 | ||
| 2299 | if (intel_rotation_90_or_270(rotation)) { | 2299 | if (drm_rotation_90_or_270(rotation)) { |
| 2300 | *x += intel_fb->rotated[plane].x; | 2300 | *x += intel_fb->rotated[plane].x; |
| 2301 | *y += intel_fb->rotated[plane].y; | 2301 | *y += intel_fb->rotated[plane].y; |
| 2302 | } else { | 2302 | } else { |
| @@ -2360,7 +2360,7 @@ static u32 intel_adjust_tile_offset(int *x, int *y, | |||
| 2360 | intel_tile_dims(dev_priv, &tile_width, &tile_height, | 2360 | intel_tile_dims(dev_priv, &tile_width, &tile_height, |
| 2361 | fb->modifier[plane], cpp); | 2361 | fb->modifier[plane], cpp); |
| 2362 | 2362 | ||
| 2363 | if (intel_rotation_90_or_270(rotation)) { | 2363 | if (drm_rotation_90_or_270(rotation)) { |
| 2364 | pitch_tiles = pitch / tile_height; | 2364 | pitch_tiles = pitch / tile_height; |
| 2365 | swap(tile_width, tile_height); | 2365 | swap(tile_width, tile_height); |
| 2366 | } else { | 2366 | } else { |
| @@ -2416,7 +2416,7 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv, | |||
| 2416 | intel_tile_dims(dev_priv, &tile_width, &tile_height, | 2416 | intel_tile_dims(dev_priv, &tile_width, &tile_height, |
| 2417 | fb_modifier, cpp); | 2417 | fb_modifier, cpp); |
| 2418 | 2418 | ||
| 2419 | if (intel_rotation_90_or_270(rotation)) { | 2419 | if (drm_rotation_90_or_270(rotation)) { |
| 2420 | pitch_tiles = pitch / tile_height; | 2420 | pitch_tiles = pitch / tile_height; |
| 2421 | swap(tile_width, tile_height); | 2421 | swap(tile_width, tile_height); |
| 2422 | } else { | 2422 | } else { |
| @@ -2976,7 +2976,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) | |||
| 2976 | int ret; | 2976 | int ret; |
| 2977 | 2977 | ||
| 2978 | /* Rotate src coordinates to match rotated GTT view */ | 2978 | /* Rotate src coordinates to match rotated GTT view */ |
| 2979 | if (intel_rotation_90_or_270(rotation)) | 2979 | if (drm_rotation_90_or_270(rotation)) |
| 2980 | drm_rect_rotate(&plane_state->base.src, | 2980 | drm_rect_rotate(&plane_state->base.src, |
| 2981 | fb->width, fb->height, DRM_ROTATE_270); | 2981 | fb->width, fb->height, DRM_ROTATE_270); |
| 2982 | 2982 | ||
| @@ -3276,7 +3276,7 @@ u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, | |||
| 3276 | * The stride is either expressed as a multiple of 64 bytes chunks for | 3276 | * The stride is either expressed as a multiple of 64 bytes chunks for |
| 3277 | * linear buffers or in number of tiles for tiled buffers. | 3277 | * linear buffers or in number of tiles for tiled buffers. |
| 3278 | */ | 3278 | */ |
| 3279 | if (intel_rotation_90_or_270(rotation)) { | 3279 | if (drm_rotation_90_or_270(rotation)) { |
| 3280 | int cpp = drm_format_plane_cpp(fb->pixel_format, plane); | 3280 | int cpp = drm_format_plane_cpp(fb->pixel_format, plane); |
| 3281 | 3281 | ||
| 3282 | stride /= intel_tile_height(dev_priv, fb->modifier[0], cpp); | 3282 | stride /= intel_tile_height(dev_priv, fb->modifier[0], cpp); |
| @@ -3584,7 +3584,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv) | |||
| 3584 | return; | 3584 | return; |
| 3585 | 3585 | ||
| 3586 | err: | 3586 | err: |
| 3587 | drm_atomic_state_free(state); | 3587 | drm_atomic_state_put(state); |
| 3588 | } | 3588 | } |
| 3589 | 3589 | ||
| 3590 | void intel_finish_reset(struct drm_i915_private *dev_priv) | 3590 | void intel_finish_reset(struct drm_i915_private *dev_priv) |
| @@ -3646,6 +3646,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) | |||
| 3646 | intel_hpd_init(dev_priv); | 3646 | intel_hpd_init(dev_priv); |
| 3647 | } | 3647 | } |
| 3648 | 3648 | ||
| 3649 | if (state) | ||
| 3650 | drm_atomic_state_put(state); | ||
| 3649 | drm_modeset_drop_locks(ctx); | 3651 | drm_modeset_drop_locks(ctx); |
| 3650 | drm_modeset_acquire_fini(ctx); | 3652 | drm_modeset_acquire_fini(ctx); |
| 3651 | mutex_unlock(&dev->mode_config.mutex); | 3653 | mutex_unlock(&dev->mode_config.mutex); |
| @@ -4667,7 +4669,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, | |||
| 4667 | to_intel_crtc(crtc_state->base.crtc); | 4669 | to_intel_crtc(crtc_state->base.crtc); |
| 4668 | int need_scaling; | 4670 | int need_scaling; |
| 4669 | 4671 | ||
| 4670 | need_scaling = intel_rotation_90_or_270(rotation) ? | 4672 | need_scaling = drm_rotation_90_or_270(rotation) ? |
| 4671 | (src_h != dst_w || src_w != dst_h): | 4673 | (src_h != dst_w || src_w != dst_h): |
| 4672 | (src_w != dst_w || src_h != dst_h); | 4674 | (src_w != dst_w || src_h != dst_h); |
| 4673 | 4675 | ||
| @@ -6885,7 +6887,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) | |||
| 6885 | 6887 | ||
| 6886 | dev_priv->display.crtc_disable(crtc_state, state); | 6888 | dev_priv->display.crtc_disable(crtc_state, state); |
| 6887 | 6889 | ||
| 6888 | drm_atomic_state_free(state); | 6890 | drm_atomic_state_put(state); |
| 6889 | 6891 | ||
| 6890 | DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", | 6892 | DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", |
| 6891 | crtc->base.id, crtc->name); | 6893 | crtc->base.id, crtc->name); |
| @@ -11270,9 +11272,14 @@ found: | |||
| 11270 | return true; | 11272 | return true; |
| 11271 | 11273 | ||
| 11272 | fail: | 11274 | fail: |
| 11273 | drm_atomic_state_free(state); | 11275 | if (state) { |
| 11274 | drm_atomic_state_free(restore_state); | 11276 | drm_atomic_state_put(state); |
| 11275 | restore_state = state = NULL; | 11277 | state = NULL; |
| 11278 | } | ||
| 11279 | if (restore_state) { | ||
| 11280 | drm_atomic_state_put(restore_state); | ||
| 11281 | restore_state = NULL; | ||
| 11282 | } | ||
| 11276 | 11283 | ||
| 11277 | if (ret == -EDEADLK) { | 11284 | if (ret == -EDEADLK) { |
| 11278 | drm_modeset_backoff(ctx); | 11285 | drm_modeset_backoff(ctx); |
| @@ -11300,10 +11307,9 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, | |||
| 11300 | return; | 11307 | return; |
| 11301 | 11308 | ||
| 11302 | ret = drm_atomic_commit(state); | 11309 | ret = drm_atomic_commit(state); |
| 11303 | if (ret) { | 11310 | if (ret) |
| 11304 | DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret); | 11311 | DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret); |
| 11305 | drm_atomic_state_free(state); | 11312 | drm_atomic_state_put(state); |
| 11306 | } | ||
| 11307 | } | 11313 | } |
| 11308 | 11314 | ||
| 11309 | static int i9xx_pll_refclk(struct drm_device *dev, | 11315 | static int i9xx_pll_refclk(struct drm_device *dev, |
| @@ -12371,8 +12377,7 @@ retry: | |||
| 12371 | goto retry; | 12377 | goto retry; |
| 12372 | } | 12378 | } |
| 12373 | 12379 | ||
| 12374 | if (ret) | 12380 | drm_atomic_state_put(state); |
| 12375 | drm_atomic_state_free(state); | ||
| 12376 | 12381 | ||
| 12377 | if (ret == 0 && event) { | 12382 | if (ret == 0 && event) { |
| 12378 | spin_lock_irq(&dev->event_lock); | 12383 | spin_lock_irq(&dev->event_lock); |
| @@ -14457,7 +14462,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) | |||
| 14457 | 14462 | ||
| 14458 | drm_atomic_helper_commit_cleanup_done(state); | 14463 | drm_atomic_helper_commit_cleanup_done(state); |
| 14459 | 14464 | ||
| 14460 | drm_atomic_state_free(state); | 14465 | drm_atomic_state_put(state); |
| 14461 | 14466 | ||
| 14462 | /* As one of the primary mmio accessors, KMS has a high likelihood | 14467 | /* As one of the primary mmio accessors, KMS has a high likelihood |
| 14463 | * of triggering bugs in unclaimed access. After we finish | 14468 | * of triggering bugs in unclaimed access. After we finish |
| @@ -14540,6 +14545,7 @@ static int intel_atomic_commit(struct drm_device *dev, | |||
| 14540 | intel_shared_dpll_commit(state); | 14545 | intel_shared_dpll_commit(state); |
| 14541 | intel_atomic_track_fbs(state); | 14546 | intel_atomic_track_fbs(state); |
| 14542 | 14547 | ||
| 14548 | drm_atomic_state_get(state); | ||
| 14543 | if (nonblock) | 14549 | if (nonblock) |
| 14544 | queue_work(system_unbound_wq, &state->commit_work); | 14550 | queue_work(system_unbound_wq, &state->commit_work); |
| 14545 | else | 14551 | else |
| @@ -14581,9 +14587,8 @@ retry: | |||
| 14581 | goto retry; | 14587 | goto retry; |
| 14582 | } | 14588 | } |
| 14583 | 14589 | ||
| 14584 | if (ret) | ||
| 14585 | out: | 14590 | out: |
| 14586 | drm_atomic_state_free(state); | 14591 | drm_atomic_state_put(state); |
| 14587 | } | 14592 | } |
| 14588 | 14593 | ||
| 14589 | /* | 14594 | /* |
| @@ -14901,6 +14906,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, | |||
| 14901 | struct intel_plane *primary = NULL; | 14906 | struct intel_plane *primary = NULL; |
| 14902 | struct intel_plane_state *state = NULL; | 14907 | struct intel_plane_state *state = NULL; |
| 14903 | const uint32_t *intel_primary_formats; | 14908 | const uint32_t *intel_primary_formats; |
| 14909 | unsigned int supported_rotations; | ||
| 14904 | unsigned int num_formats; | 14910 | unsigned int num_formats; |
| 14905 | int ret; | 14911 | int ret; |
| 14906 | 14912 | ||
| @@ -14973,8 +14979,21 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, | |||
| 14973 | if (ret) | 14979 | if (ret) |
| 14974 | goto fail; | 14980 | goto fail; |
| 14975 | 14981 | ||
| 14976 | if (INTEL_INFO(dev)->gen >= 4) | 14982 | if (INTEL_GEN(dev) >= 9) { |
| 14977 | intel_create_rotation_property(dev, primary); | 14983 | supported_rotations = |
| 14984 | DRM_ROTATE_0 | DRM_ROTATE_90 | | ||
| 14985 | DRM_ROTATE_180 | DRM_ROTATE_270; | ||
| 14986 | } else if (INTEL_GEN(dev) >= 4) { | ||
| 14987 | supported_rotations = | ||
| 14988 | DRM_ROTATE_0 | DRM_ROTATE_180; | ||
| 14989 | } else { | ||
| 14990 | supported_rotations = DRM_ROTATE_0; | ||
| 14991 | } | ||
| 14992 | |||
| 14993 | if (INTEL_GEN(dev) >= 4) | ||
| 14994 | drm_plane_create_rotation_property(&primary->base, | ||
| 14995 | DRM_ROTATE_0, | ||
| 14996 | supported_rotations); | ||
| 14978 | 14997 | ||
| 14979 | drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); | 14998 | drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); |
| 14980 | 14999 | ||
| @@ -14987,24 +15006,6 @@ fail: | |||
| 14987 | return NULL; | 15006 | return NULL; |
| 14988 | } | 15007 | } |
| 14989 | 15008 | ||
| 14990 | void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane) | ||
| 14991 | { | ||
| 14992 | if (!dev->mode_config.rotation_property) { | ||
| 14993 | unsigned long flags = DRM_ROTATE_0 | | ||
| 14994 | DRM_ROTATE_180; | ||
| 14995 | |||
| 14996 | if (INTEL_INFO(dev)->gen >= 9) | ||
| 14997 | flags |= DRM_ROTATE_90 | DRM_ROTATE_270; | ||
| 14998 | |||
| 14999 | dev->mode_config.rotation_property = | ||
| 15000 | drm_mode_create_rotation_property(dev, flags); | ||
| 15001 | } | ||
| 15002 | if (dev->mode_config.rotation_property) | ||
| 15003 | drm_object_attach_property(&plane->base.base, | ||
| 15004 | dev->mode_config.rotation_property, | ||
| 15005 | plane->base.state->rotation); | ||
| 15006 | } | ||
| 15007 | |||
| 15008 | static int | 15009 | static int |
| 15009 | intel_check_cursor_plane(struct drm_plane *plane, | 15010 | intel_check_cursor_plane(struct drm_plane *plane, |
| 15010 | struct intel_crtc_state *crtc_state, | 15011 | struct intel_crtc_state *crtc_state, |
| @@ -15131,17 +15132,11 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, | |||
| 15131 | if (ret) | 15132 | if (ret) |
| 15132 | goto fail; | 15133 | goto fail; |
| 15133 | 15134 | ||
| 15134 | if (INTEL_INFO(dev)->gen >= 4) { | 15135 | if (INTEL_GEN(dev) >= 4) |
| 15135 | if (!dev->mode_config.rotation_property) | 15136 | drm_plane_create_rotation_property(&cursor->base, |
| 15136 | dev->mode_config.rotation_property = | 15137 | DRM_ROTATE_0, |
| 15137 | drm_mode_create_rotation_property(dev, | 15138 | DRM_ROTATE_0 | |
| 15138 | DRM_ROTATE_0 | | 15139 | DRM_ROTATE_180); |
| 15139 | DRM_ROTATE_180); | ||
| 15140 | if (dev->mode_config.rotation_property) | ||
| 15141 | drm_object_attach_property(&cursor->base.base, | ||
| 15142 | dev->mode_config.rotation_property, | ||
| 15143 | state->base.rotation); | ||
| 15144 | } | ||
| 15145 | 15140 | ||
| 15146 | if (INTEL_INFO(dev)->gen >=9) | 15141 | if (INTEL_INFO(dev)->gen >=9) |
| 15147 | state->scaler_id = -1; | 15142 | state->scaler_id = -1; |
| @@ -16314,7 +16309,7 @@ retry: | |||
| 16314 | * BIOS-programmed watermarks untouched and hope for the best. | 16309 | * BIOS-programmed watermarks untouched and hope for the best. |
| 16315 | */ | 16310 | */ |
| 16316 | WARN(true, "Could not determine valid watermarks for inherited state\n"); | 16311 | WARN(true, "Could not determine valid watermarks for inherited state\n"); |
| 16317 | goto fail; | 16312 | goto put_state; |
| 16318 | } | 16313 | } |
| 16319 | 16314 | ||
| 16320 | /* Write calculated watermark values back */ | 16315 | /* Write calculated watermark values back */ |
| @@ -16325,7 +16320,8 @@ retry: | |||
| 16325 | dev_priv->display.optimize_watermarks(cs); | 16320 | dev_priv->display.optimize_watermarks(cs); |
| 16326 | } | 16321 | } |
| 16327 | 16322 | ||
| 16328 | drm_atomic_state_free(state); | 16323 | put_state: |
| 16324 | drm_atomic_state_put(state); | ||
| 16329 | fail: | 16325 | fail: |
| 16330 | drm_modeset_drop_locks(&ctx); | 16326 | drm_modeset_drop_locks(&ctx); |
| 16331 | drm_modeset_acquire_fini(&ctx); | 16327 | drm_modeset_acquire_fini(&ctx); |
| @@ -16963,10 +16959,9 @@ void intel_display_resume(struct drm_device *dev) | |||
| 16963 | drm_modeset_acquire_fini(&ctx); | 16959 | drm_modeset_acquire_fini(&ctx); |
| 16964 | mutex_unlock(&dev->mode_config.mutex); | 16960 | mutex_unlock(&dev->mode_config.mutex); |
| 16965 | 16961 | ||
| 16966 | if (ret) { | 16962 | if (ret) |
| 16967 | DRM_ERROR("Restoring old state failed with %i\n", ret); | 16963 | DRM_ERROR("Restoring old state failed with %i\n", ret); |
| 16968 | drm_atomic_state_free(state); | 16964 | drm_atomic_state_put(state); |
| 16969 | } | ||
| 16970 | } | 16965 | } |
| 16971 | 16966 | ||
| 16972 | void intel_modeset_gem_init(struct drm_device *dev) | 16967 | void intel_modeset_gem_init(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a19ec06f9e42..3ffba2def09c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -1285,15 +1285,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, | |||
| 1285 | unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, | 1285 | unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, |
| 1286 | uint64_t fb_modifier, unsigned int cpp); | 1286 | uint64_t fb_modifier, unsigned int cpp); |
| 1287 | 1287 | ||
| 1288 | static inline bool | ||
| 1289 | intel_rotation_90_or_270(unsigned int rotation) | ||
| 1290 | { | ||
| 1291 | return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270); | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | void intel_create_rotation_property(struct drm_device *dev, | ||
| 1295 | struct intel_plane *plane); | ||
| 1296 | |||
| 1297 | void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, | 1288 | void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, |
| 1298 | enum pipe pipe); | 1289 | enum pipe pipe); |
| 1299 | 1290 | ||
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index faa67624e1ed..afc040be1172 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c | |||
| @@ -84,7 +84,7 @@ static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache, | |||
| 84 | { | 84 | { |
| 85 | int w, h; | 85 | int w, h; |
| 86 | 86 | ||
| 87 | if (intel_rotation_90_or_270(cache->plane.rotation)) { | 87 | if (drm_rotation_90_or_270(cache->plane.rotation)) { |
| 88 | w = cache->plane.src_h; | 88 | w = cache->plane.src_h; |
| 89 | h = cache->plane.src_w; | 89 | h = cache->plane.src_w; |
| 90 | } else { | 90 | } else { |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a2f751cd187a..e2f0a32279e7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -3173,7 +3173,7 @@ skl_plane_downscale_amount(const struct intel_plane_state *pstate) | |||
| 3173 | src_h = drm_rect_height(&pstate->base.src); | 3173 | src_h = drm_rect_height(&pstate->base.src); |
| 3174 | dst_w = drm_rect_width(&pstate->base.dst); | 3174 | dst_w = drm_rect_width(&pstate->base.dst); |
| 3175 | dst_h = drm_rect_height(&pstate->base.dst); | 3175 | dst_h = drm_rect_height(&pstate->base.dst); |
| 3176 | if (intel_rotation_90_or_270(pstate->base.rotation)) | 3176 | if (drm_rotation_90_or_270(pstate->base.rotation)) |
| 3177 | swap(dst_w, dst_h); | 3177 | swap(dst_w, dst_h); |
| 3178 | 3178 | ||
| 3179 | downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING); | 3179 | downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING); |
| @@ -3204,7 +3204,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, | |||
| 3204 | width = drm_rect_width(&intel_pstate->base.src) >> 16; | 3204 | width = drm_rect_width(&intel_pstate->base.src) >> 16; |
| 3205 | height = drm_rect_height(&intel_pstate->base.src) >> 16; | 3205 | height = drm_rect_height(&intel_pstate->base.src) >> 16; |
| 3206 | 3206 | ||
| 3207 | if (intel_rotation_90_or_270(pstate->rotation)) | 3207 | if (drm_rotation_90_or_270(pstate->rotation)) |
| 3208 | swap(width, height); | 3208 | swap(width, height); |
| 3209 | 3209 | ||
| 3210 | /* for planar format */ | 3210 | /* for planar format */ |
| @@ -3304,7 +3304,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, | |||
| 3304 | src_w = drm_rect_width(&intel_pstate->base.src) >> 16; | 3304 | src_w = drm_rect_width(&intel_pstate->base.src) >> 16; |
| 3305 | src_h = drm_rect_height(&intel_pstate->base.src) >> 16; | 3305 | src_h = drm_rect_height(&intel_pstate->base.src) >> 16; |
| 3306 | 3306 | ||
| 3307 | if (intel_rotation_90_or_270(pstate->rotation)) | 3307 | if (drm_rotation_90_or_270(pstate->rotation)) |
| 3308 | swap(src_w, src_h); | 3308 | swap(src_w, src_h); |
| 3309 | 3309 | ||
| 3310 | /* Halve UV plane width and height for NV12 */ | 3310 | /* Halve UV plane width and height for NV12 */ |
| @@ -3318,7 +3318,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, | |||
| 3318 | else | 3318 | else |
| 3319 | plane_bpp = drm_format_plane_cpp(fb->pixel_format, 0); | 3319 | plane_bpp = drm_format_plane_cpp(fb->pixel_format, 0); |
| 3320 | 3320 | ||
| 3321 | if (intel_rotation_90_or_270(pstate->rotation)) { | 3321 | if (drm_rotation_90_or_270(pstate->rotation)) { |
| 3322 | switch (plane_bpp) { | 3322 | switch (plane_bpp) { |
| 3323 | case 1: | 3323 | case 1: |
| 3324 | min_scanlines = 32; | 3324 | min_scanlines = 32; |
| @@ -3562,13 +3562,13 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
| 3562 | width = drm_rect_width(&intel_pstate->base.src) >> 16; | 3562 | width = drm_rect_width(&intel_pstate->base.src) >> 16; |
| 3563 | height = drm_rect_height(&intel_pstate->base.src) >> 16; | 3563 | height = drm_rect_height(&intel_pstate->base.src) >> 16; |
| 3564 | 3564 | ||
| 3565 | if (intel_rotation_90_or_270(pstate->rotation)) | 3565 | if (drm_rotation_90_or_270(pstate->rotation)) |
| 3566 | swap(width, height); | 3566 | swap(width, height); |
| 3567 | 3567 | ||
| 3568 | cpp = drm_format_plane_cpp(fb->pixel_format, 0); | 3568 | cpp = drm_format_plane_cpp(fb->pixel_format, 0); |
| 3569 | plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); | 3569 | plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); |
| 3570 | 3570 | ||
| 3571 | if (intel_rotation_90_or_270(pstate->rotation)) { | 3571 | if (drm_rotation_90_or_270(pstate->rotation)) { |
| 3572 | int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? | 3572 | int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? |
| 3573 | drm_format_plane_cpp(fb->pixel_format, 1) : | 3573 | drm_format_plane_cpp(fb->pixel_format, 1) : |
| 3574 | drm_format_plane_cpp(fb->pixel_format, 0); | 3574 | drm_format_plane_cpp(fb->pixel_format, 0); |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 73a521fdf1bd..3ea6419e18b9 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
| @@ -987,9 +987,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | |||
| 987 | drm_modeset_backoff(&ctx); | 987 | drm_modeset_backoff(&ctx); |
| 988 | } | 988 | } |
| 989 | 989 | ||
| 990 | if (ret) | 990 | drm_atomic_state_put(state); |
| 991 | drm_atomic_state_free(state); | ||
| 992 | |||
| 993 | out: | 991 | out: |
| 994 | drm_modeset_drop_locks(&ctx); | 992 | drm_modeset_drop_locks(&ctx); |
| 995 | drm_modeset_acquire_fini(&ctx); | 993 | drm_modeset_acquire_fini(&ctx); |
| @@ -1046,6 +1044,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
| 1046 | struct intel_plane_state *state = NULL; | 1044 | struct intel_plane_state *state = NULL; |
| 1047 | unsigned long possible_crtcs; | 1045 | unsigned long possible_crtcs; |
| 1048 | const uint32_t *plane_formats; | 1046 | const uint32_t *plane_formats; |
| 1047 | unsigned int supported_rotations; | ||
| 1049 | int num_plane_formats; | 1048 | int num_plane_formats; |
| 1050 | int ret; | 1049 | int ret; |
| 1051 | 1050 | ||
| @@ -1121,6 +1120,15 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
| 1121 | goto fail; | 1120 | goto fail; |
| 1122 | } | 1121 | } |
| 1123 | 1122 | ||
| 1123 | if (INTEL_GEN(dev) >= 9) { | ||
| 1124 | supported_rotations = | ||
| 1125 | DRM_ROTATE_0 | DRM_ROTATE_90 | | ||
| 1126 | DRM_ROTATE_180 | DRM_ROTATE_270; | ||
| 1127 | } else { | ||
| 1128 | supported_rotations = | ||
| 1129 | DRM_ROTATE_0 | DRM_ROTATE_180; | ||
| 1130 | } | ||
| 1131 | |||
| 1124 | intel_plane->pipe = pipe; | 1132 | intel_plane->pipe = pipe; |
| 1125 | intel_plane->plane = plane; | 1133 | intel_plane->plane = plane; |
| 1126 | intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); | 1134 | intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); |
| @@ -1143,7 +1151,9 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
| 1143 | if (ret) | 1151 | if (ret) |
| 1144 | goto fail; | 1152 | goto fail; |
| 1145 | 1153 | ||
| 1146 | intel_create_rotation_property(dev, intel_plane); | 1154 | drm_plane_create_rotation_property(&intel_plane->base, |
| 1155 | DRM_ROTATE_0, | ||
| 1156 | supported_rotations); | ||
| 1147 | 1157 | ||
| 1148 | drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); | 1158 | drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); |
| 1149 | 1159 | ||
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index cf83f6507ec8..db61aa5f32ef 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c | |||
| @@ -83,7 +83,7 @@ static void mtk_atomic_complete(struct mtk_drm_private *private, | |||
| 83 | drm_atomic_helper_wait_for_vblanks(drm, state); | 83 | drm_atomic_helper_wait_for_vblanks(drm, state); |
| 84 | 84 | ||
| 85 | drm_atomic_helper_cleanup_planes(drm, state); | 85 | drm_atomic_helper_cleanup_planes(drm, state); |
| 86 | drm_atomic_state_free(state); | 86 | drm_atomic_state_put(state); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | static void mtk_atomic_work(struct work_struct *work) | 89 | static void mtk_atomic_work(struct work_struct *work) |
| @@ -110,6 +110,7 @@ static int mtk_atomic_commit(struct drm_device *drm, | |||
| 110 | 110 | ||
| 111 | drm_atomic_helper_swap_state(state, true); | 111 | drm_atomic_helper_swap_state(state, true); |
| 112 | 112 | ||
| 113 | drm_atomic_state_get(state); | ||
| 113 | if (async) | 114 | if (async) |
| 114 | mtk_atomic_schedule(private, state); | 115 | mtk_atomic_schedule(private, state); |
| 115 | else | 116 | else |
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 73bae382eac3..db193f835298 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c | |||
| @@ -141,7 +141,7 @@ static void complete_commit(struct msm_commit *c, bool async) | |||
| 141 | 141 | ||
| 142 | kms->funcs->complete_commit(kms, state); | 142 | kms->funcs->complete_commit(kms, state); |
| 143 | 143 | ||
| 144 | drm_atomic_state_free(state); | 144 | drm_atomic_state_put(state); |
| 145 | 145 | ||
| 146 | commit_destroy(c); | 146 | commit_destroy(c); |
| 147 | } | 147 | } |
| @@ -256,6 +256,7 @@ int msm_atomic_commit(struct drm_device *dev, | |||
| 256 | * current layout. | 256 | * current layout. |
| 257 | */ | 257 | */ |
| 258 | 258 | ||
| 259 | drm_atomic_state_get(state); | ||
| 259 | if (nonblock) { | 260 | if (nonblock) { |
| 260 | queue_work(priv->atomic_wq, &c->work); | 261 | queue_work(priv->atomic_wq, &c->work); |
| 261 | return 0; | 262 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 72e2399bce39..0bd7164bc817 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -861,6 +861,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, | |||
| 861 | struct nouveau_bo *nvbo; | 861 | struct nouveau_bo *nvbo; |
| 862 | bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); | 862 | bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); |
| 863 | bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE); | 863 | bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE); |
| 864 | long lret; | ||
| 864 | int ret; | 865 | int ret; |
| 865 | 866 | ||
| 866 | gem = drm_gem_object_lookup(file_priv, req->handle); | 867 | gem = drm_gem_object_lookup(file_priv, req->handle); |
| @@ -868,19 +869,15 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, | |||
| 868 | return -ENOENT; | 869 | return -ENOENT; |
| 869 | nvbo = nouveau_gem_object(gem); | 870 | nvbo = nouveau_gem_object(gem); |
| 870 | 871 | ||
| 871 | if (no_wait) | 872 | lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, |
| 872 | ret = reservation_object_test_signaled_rcu(nvbo->bo.resv, write) ? 0 : -EBUSY; | 873 | no_wait ? 0 : 30 * HZ); |
| 873 | else { | 874 | if (!lret) |
| 874 | long lret; | 875 | ret = -EBUSY; |
| 876 | else if (lret > 0) | ||
| 877 | ret = 0; | ||
| 878 | else | ||
| 879 | ret = lret; | ||
| 875 | 880 | ||
| 876 | lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, 30 * HZ); | ||
| 877 | if (!lret) | ||
| 878 | ret = -EBUSY; | ||
| 879 | else if (lret > 0) | ||
| 880 | ret = 0; | ||
| 881 | else | ||
| 882 | ret = lret; | ||
| 883 | } | ||
| 884 | nouveau_bo_sync_for_cpu(nvbo); | 881 | nouveau_bo_sync_for_cpu(nvbo); |
| 885 | drm_gem_object_unreference_unlocked(gem); | 882 | drm_gem_object_unreference_unlocked(gem); |
| 886 | 883 | ||
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 180f644e861e..16c691dbc372 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
| @@ -438,13 +438,14 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, | |||
| 438 | } | 438 | } |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | static bool omap_crtc_is_plane_prop(struct drm_device *dev, | 441 | static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc, |
| 442 | struct drm_property *property) | 442 | struct drm_property *property) |
| 443 | { | 443 | { |
| 444 | struct drm_device *dev = crtc->dev; | ||
| 444 | struct omap_drm_private *priv = dev->dev_private; | 445 | struct omap_drm_private *priv = dev->dev_private; |
| 445 | 446 | ||
| 446 | return property == priv->zorder_prop || | 447 | return property == priv->zorder_prop || |
| 447 | property == dev->mode_config.rotation_property; | 448 | property == crtc->primary->rotation_property; |
| 448 | } | 449 | } |
| 449 | 450 | ||
| 450 | static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, | 451 | static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, |
| @@ -452,9 +453,7 @@ static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, | |||
| 452 | struct drm_property *property, | 453 | struct drm_property *property, |
| 453 | uint64_t val) | 454 | uint64_t val) |
| 454 | { | 455 | { |
| 455 | struct drm_device *dev = crtc->dev; | 456 | if (omap_crtc_is_plane_prop(crtc, property)) { |
| 456 | |||
| 457 | if (omap_crtc_is_plane_prop(dev, property)) { | ||
| 458 | struct drm_plane_state *plane_state; | 457 | struct drm_plane_state *plane_state; |
| 459 | struct drm_plane *plane = crtc->primary; | 458 | struct drm_plane *plane = crtc->primary; |
| 460 | 459 | ||
| @@ -479,9 +478,7 @@ static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, | |||
| 479 | struct drm_property *property, | 478 | struct drm_property *property, |
| 480 | uint64_t *val) | 479 | uint64_t *val) |
| 481 | { | 480 | { |
| 482 | struct drm_device *dev = crtc->dev; | 481 | if (omap_crtc_is_plane_prop(crtc, property)) { |
| 483 | |||
| 484 | if (omap_crtc_is_plane_prop(dev, property)) { | ||
| 485 | /* | 482 | /* |
| 486 | * Delegate property get to the primary plane. The | 483 | * Delegate property get to the primary plane. The |
| 487 | * drm_atomic_plane_get_property() function isn't exported, but | 484 | * drm_atomic_plane_get_property() function isn't exported, but |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index e1cfba51cff6..39c5312b466c 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
| @@ -105,7 +105,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) | |||
| 105 | 105 | ||
| 106 | dispc_runtime_put(); | 106 | dispc_runtime_put(); |
| 107 | 107 | ||
| 108 | drm_atomic_state_free(old_state); | 108 | drm_atomic_state_put(old_state); |
| 109 | 109 | ||
| 110 | /* Complete the commit, wake up any waiter. */ | 110 | /* Complete the commit, wake up any waiter. */ |
| 111 | spin_lock(&priv->commit.lock); | 111 | spin_lock(&priv->commit.lock); |
| @@ -176,6 +176,7 @@ static int omap_atomic_commit(struct drm_device *dev, | |||
| 176 | /* Swap the state, this is the point of no return. */ | 176 | /* Swap the state, this is the point of no return. */ |
| 177 | drm_atomic_helper_swap_state(state, true); | 177 | drm_atomic_helper_swap_state(state, true); |
| 178 | 178 | ||
| 179 | drm_atomic_state_get(state); | ||
| 179 | if (nonblock) | 180 | if (nonblock) |
| 180 | schedule_work(&commit->work); | 181 | schedule_work(&commit->work); |
| 181 | else | 182 | else |
| @@ -292,16 +293,6 @@ static int omap_modeset_init_properties(struct drm_device *dev) | |||
| 292 | { | 293 | { |
| 293 | struct omap_drm_private *priv = dev->dev_private; | 294 | struct omap_drm_private *priv = dev->dev_private; |
| 294 | 295 | ||
| 295 | if (priv->has_dmm) { | ||
| 296 | dev->mode_config.rotation_property = | ||
| 297 | drm_mode_create_rotation_property(dev, | ||
| 298 | DRM_ROTATE_0 | DRM_ROTATE_90 | | ||
| 299 | DRM_ROTATE_180 | DRM_ROTATE_270 | | ||
| 300 | DRM_REFLECT_X | DRM_REFLECT_Y); | ||
| 301 | if (!dev->mode_config.rotation_property) | ||
| 302 | return -ENOMEM; | ||
| 303 | } | ||
| 304 | |||
| 305 | priv->zorder_prop = drm_property_create_range(dev, 0, "zorder", 0, 3); | 296 | priv->zorder_prop = drm_property_create_range(dev, 0, "zorder", 0, 3); |
| 306 | if (!priv->zorder_prop) | 297 | if (!priv->zorder_prop) |
| 307 | return -ENOMEM; | 298 | return -ENOMEM; |
| @@ -752,22 +743,32 @@ static void dev_lastclose(struct drm_device *dev) | |||
| 752 | 743 | ||
| 753 | DBG("lastclose: dev=%p", dev); | 744 | DBG("lastclose: dev=%p", dev); |
| 754 | 745 | ||
| 755 | if (dev->mode_config.rotation_property) { | 746 | /* need to restore default rotation state.. not sure |
| 756 | /* need to restore default rotation state.. not sure | 747 | * if there is a cleaner way to restore properties to |
| 757 | * if there is a cleaner way to restore properties to | 748 | * default state? Maybe a flag that properties should |
| 758 | * default state? Maybe a flag that properties should | 749 | * automatically be restored to default state on |
| 759 | * automatically be restored to default state on | 750 | * lastclose? |
| 760 | * lastclose? | 751 | */ |
| 761 | */ | 752 | for (i = 0; i < priv->num_crtcs; i++) { |
| 762 | for (i = 0; i < priv->num_crtcs; i++) { | 753 | struct drm_crtc *crtc = priv->crtcs[i]; |
| 763 | drm_object_property_set_value(&priv->crtcs[i]->base, | ||
| 764 | dev->mode_config.rotation_property, 0); | ||
| 765 | } | ||
| 766 | 754 | ||
| 767 | for (i = 0; i < priv->num_planes; i++) { | 755 | if (!crtc->primary->rotation_property) |
| 768 | drm_object_property_set_value(&priv->planes[i]->base, | 756 | continue; |
| 769 | dev->mode_config.rotation_property, 0); | 757 | |
| 770 | } | 758 | drm_object_property_set_value(&crtc->base, |
| 759 | crtc->primary->rotation_property, | ||
| 760 | DRM_ROTATE_0); | ||
| 761 | } | ||
| 762 | |||
| 763 | for (i = 0; i < priv->num_planes; i++) { | ||
| 764 | struct drm_plane *plane = priv->planes[i]; | ||
| 765 | |||
| 766 | if (!plane->rotation_property) | ||
| 767 | continue; | ||
| 768 | |||
| 769 | drm_object_property_set_value(&plane->base, | ||
| 770 | plane->rotation_property, | ||
| 771 | DRM_ROTATE_0); | ||
| 771 | } | 772 | } |
| 772 | 773 | ||
| 773 | if (priv->fbdev) { | 774 | if (priv->fbdev) { |
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 66ac8c40db26..0ffd5b930ec0 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c | |||
| @@ -108,16 +108,12 @@ static void omap_plane_atomic_update(struct drm_plane *plane, | |||
| 108 | win.src_x = state->src_x >> 16; | 108 | win.src_x = state->src_x >> 16; |
| 109 | win.src_y = state->src_y >> 16; | 109 | win.src_y = state->src_y >> 16; |
| 110 | 110 | ||
| 111 | switch (state->rotation & DRM_ROTATE_MASK) { | 111 | if (drm_rotation_90_or_270(state->rotation)) { |
| 112 | case DRM_ROTATE_90: | ||
| 113 | case DRM_ROTATE_270: | ||
| 114 | win.src_w = state->src_h >> 16; | 112 | win.src_w = state->src_h >> 16; |
| 115 | win.src_h = state->src_w >> 16; | 113 | win.src_h = state->src_w >> 16; |
| 116 | break; | 114 | } else { |
| 117 | default: | ||
| 118 | win.src_w = state->src_w >> 16; | 115 | win.src_w = state->src_w >> 16; |
| 119 | win.src_h = state->src_h >> 16; | 116 | win.src_h = state->src_h >> 16; |
| 120 | break; | ||
| 121 | } | 117 | } |
| 122 | 118 | ||
| 123 | /* update scanout: */ | 119 | /* update scanout: */ |
| @@ -215,9 +211,17 @@ void omap_plane_install_properties(struct drm_plane *plane, | |||
| 215 | struct omap_drm_private *priv = dev->dev_private; | 211 | struct omap_drm_private *priv = dev->dev_private; |
| 216 | 212 | ||
| 217 | if (priv->has_dmm) { | 213 | if (priv->has_dmm) { |
| 218 | struct drm_property *prop = dev->mode_config.rotation_property; | 214 | if (!plane->rotation_property) |
| 219 | 215 | drm_plane_create_rotation_property(plane, | |
| 220 | drm_object_attach_property(obj, prop, 0); | 216 | DRM_ROTATE_0, |
| 217 | DRM_ROTATE_0 | DRM_ROTATE_90 | | ||
| 218 | DRM_ROTATE_180 | DRM_ROTATE_270 | | ||
| 219 | DRM_REFLECT_X | DRM_REFLECT_Y); | ||
| 220 | |||
| 221 | /* Attach the rotation property also to the crtc object */ | ||
| 222 | if (plane->rotation_property && obj != &plane->base) | ||
| 223 | drm_object_attach_property(obj, plane->rotation_property, | ||
| 224 | DRM_ROTATE_0); | ||
| 221 | } | 225 | } |
| 222 | 226 | ||
| 223 | drm_object_attach_property(obj, priv->zorder_prop, 0); | 227 | drm_object_attach_property(obj, priv->zorder_prop, 0); |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 0daad446d2c7..f65f29911dca 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
| @@ -89,13 +89,13 @@ static struct fb_ops radeonfb_ops = { | |||
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | 91 | ||
| 92 | int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) | 92 | int radeon_align_pitch(struct radeon_device *rdev, int width, int cpp, bool tiled) |
| 93 | { | 93 | { |
| 94 | int aligned = width; | 94 | int aligned = width; |
| 95 | int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; | 95 | int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; |
| 96 | int pitch_mask = 0; | 96 | int pitch_mask = 0; |
| 97 | 97 | ||
| 98 | switch (bpp / 8) { | 98 | switch (cpp) { |
| 99 | case 1: | 99 | case 1: |
| 100 | pitch_mask = align_large ? 255 : 127; | 100 | pitch_mask = align_large ? 255 : 127; |
| 101 | break; | 101 | break; |
| @@ -110,7 +110,7 @@ int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tile | |||
| 110 | 110 | ||
| 111 | aligned += pitch_mask; | 111 | aligned += pitch_mask; |
| 112 | aligned &= ~pitch_mask; | 112 | aligned &= ~pitch_mask; |
| 113 | return aligned; | 113 | return aligned * cpp; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) | 116 | static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) |
| @@ -139,13 +139,13 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, | |||
| 139 | int ret; | 139 | int ret; |
| 140 | int aligned_size, size; | 140 | int aligned_size, size; |
| 141 | int height = mode_cmd->height; | 141 | int height = mode_cmd->height; |
| 142 | u32 bpp, depth; | 142 | u32 cpp; |
| 143 | 143 | ||
| 144 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); | 144 | cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0); |
| 145 | 145 | ||
| 146 | /* need to align pitch with crtc limits */ | 146 | /* need to align pitch with crtc limits */ |
| 147 | mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp, | 147 | mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp, |
| 148 | fb_tiled) * ((bpp + 1) / 8); | 148 | fb_tiled); |
| 149 | 149 | ||
| 150 | if (rdev->family >= CHIP_R600) | 150 | if (rdev->family >= CHIP_R600) |
| 151 | height = ALIGN(mode_cmd->height, 8); | 151 | height = ALIGN(mode_cmd->height, 8); |
| @@ -165,11 +165,11 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, | |||
| 165 | tiling_flags = RADEON_TILING_MACRO; | 165 | tiling_flags = RADEON_TILING_MACRO; |
| 166 | 166 | ||
| 167 | #ifdef __BIG_ENDIAN | 167 | #ifdef __BIG_ENDIAN |
| 168 | switch (bpp) { | 168 | switch (cpp) { |
| 169 | case 32: | 169 | case 4: |
| 170 | tiling_flags |= RADEON_TILING_SWAP_32BIT; | 170 | tiling_flags |= RADEON_TILING_SWAP_32BIT; |
| 171 | break; | 171 | break; |
| 172 | case 16: | 172 | case 2: |
| 173 | tiling_flags |= RADEON_TILING_SWAP_16BIT; | 173 | tiling_flags |= RADEON_TILING_SWAP_16BIT; |
| 174 | default: | 174 | default: |
| 175 | break; | 175 | break; |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index deb9511725c9..0bcffd8a7bd3 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -745,7 +745,8 @@ int radeon_mode_dumb_create(struct drm_file *file_priv, | |||
| 745 | uint32_t handle; | 745 | uint32_t handle; |
| 746 | int r; | 746 | int r; |
| 747 | 747 | ||
| 748 | args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); | 748 | args->pitch = radeon_align_pitch(rdev, args->width, |
| 749 | DIV_ROUND_UP(args->bpp, 8), 0); | ||
| 749 | args->size = args->pitch * args->height; | 750 | args->size = args->pitch * args->height; |
| 750 | args->size = ALIGN(args->size, PAGE_SIZE); | 751 | args->size = ALIGN(args->size, PAGE_SIZE); |
| 751 | 752 | ||
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index bd9c3bb9252c..c76ed9ee6a01 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c | |||
| @@ -264,7 +264,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit) | |||
| 264 | 264 | ||
| 265 | drm_atomic_helper_cleanup_planes(dev, old_state); | 265 | drm_atomic_helper_cleanup_planes(dev, old_state); |
| 266 | 266 | ||
| 267 | drm_atomic_state_free(old_state); | 267 | drm_atomic_state_put(old_state); |
| 268 | 268 | ||
| 269 | /* Complete the commit, wake up any waiter. */ | 269 | /* Complete the commit, wake up any waiter. */ |
| 270 | spin_lock(&rcdu->commit.wait.lock); | 270 | spin_lock(&rcdu->commit.wait.lock); |
| @@ -330,6 +330,7 @@ static int rcar_du_atomic_commit(struct drm_device *dev, | |||
| 330 | /* Swap the state, this is the point of no return. */ | 330 | /* Swap the state, this is the point of no return. */ |
| 331 | drm_atomic_helper_swap_state(state, true); | 331 | drm_atomic_helper_swap_state(state, true); |
| 332 | 332 | ||
| 333 | drm_atomic_state_get(state); | ||
| 333 | if (nonblock) | 334 | if (nonblock) |
| 334 | schedule_work(&commit->work); | 335 | schedule_work(&commit->work); |
| 335 | else | 336 | else |
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 3c58669a06ce..6f7f9c59f05b 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | config DRM_ROCKCHIP | 1 | config DRM_ROCKCHIP |
| 2 | tristate "DRM Support for Rockchip" | 2 | tristate "DRM Support for Rockchip" |
| 3 | depends on DRM && ROCKCHIP_IOMMU | 3 | depends on DRM && ROCKCHIP_IOMMU |
| 4 | depends on RESET_CONTROLLER | ||
| 5 | select DRM_GEM_CMA_HELPER | 4 | select DRM_GEM_CMA_HELPER |
| 6 | select DRM_KMS_HELPER | 5 | select DRM_KMS_HELPER |
| 7 | select DRM_PANEL | 6 | select DRM_PANEL |
diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c index 3dc0d8ff95ec..2db89bed52e8 100644 --- a/drivers/gpu/drm/savage/savage_state.c +++ b/drivers/gpu/drm/savage/savage_state.c | |||
| @@ -1004,6 +1004,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ | |||
| 1004 | kvb_addr = memdup_user(cmdbuf->vb_addr, cmdbuf->vb_size); | 1004 | kvb_addr = memdup_user(cmdbuf->vb_addr, cmdbuf->vb_size); |
| 1005 | if (IS_ERR(kvb_addr)) { | 1005 | if (IS_ERR(kvb_addr)) { |
| 1006 | ret = PTR_ERR(kvb_addr); | 1006 | ret = PTR_ERR(kvb_addr); |
| 1007 | kvb_addr = NULL; | ||
| 1007 | goto done; | 1008 | goto done; |
| 1008 | } | 1009 | } |
| 1009 | cmdbuf->vb_addr = kvb_addr; | 1010 | cmdbuf->vb_addr = kvb_addr; |
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 2784919a7366..7087499969bc 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c | |||
| @@ -184,7 +184,7 @@ static void sti_atomic_complete(struct sti_private *private, | |||
| 184 | drm_atomic_helper_wait_for_vblanks(drm, state); | 184 | drm_atomic_helper_wait_for_vblanks(drm, state); |
| 185 | 185 | ||
| 186 | drm_atomic_helper_cleanup_planes(drm, state); | 186 | drm_atomic_helper_cleanup_planes(drm, state); |
| 187 | drm_atomic_state_free(state); | 187 | drm_atomic_state_put(state); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | static void sti_atomic_work(struct work_struct *work) | 190 | static void sti_atomic_work(struct work_struct *work) |
| @@ -217,6 +217,7 @@ static int sti_atomic_commit(struct drm_device *drm, | |||
| 217 | 217 | ||
| 218 | drm_atomic_helper_swap_state(state, true); | 218 | drm_atomic_helper_swap_state(state, true); |
| 219 | 219 | ||
| 220 | drm_atomic_state_get(state); | ||
| 220 | if (nonblock) | 221 | if (nonblock) |
| 221 | sti_atomic_schedule(private, state); | 222 | sti_atomic_schedule(private, state); |
| 222 | else | 223 | else |
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index 63ebb154b9b5..bbf5a4b7e0b6 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig | |||
| @@ -3,7 +3,6 @@ config DRM_TEGRA | |||
| 3 | depends on ARCH_TEGRA || (ARM && COMPILE_TEST) | 3 | depends on ARCH_TEGRA || (ARM && COMPILE_TEST) |
| 4 | depends on COMMON_CLK | 4 | depends on COMMON_CLK |
| 5 | depends on DRM | 5 | depends on DRM |
| 6 | depends on RESET_CONTROLLER | ||
| 7 | select DRM_KMS_HELPER | 6 | select DRM_KMS_HELPER |
| 8 | select DRM_MIPI_DSI | 7 | select DRM_MIPI_DSI |
| 9 | select DRM_PANEL | 8 | select DRM_PANEL |
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 8ab47b502d83..a9630c2d6cb3 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
| @@ -63,7 +63,7 @@ static void tegra_atomic_complete(struct tegra_drm *tegra, | |||
| 63 | drm_atomic_helper_wait_for_vblanks(drm, state); | 63 | drm_atomic_helper_wait_for_vblanks(drm, state); |
| 64 | 64 | ||
| 65 | drm_atomic_helper_cleanup_planes(drm, state); | 65 | drm_atomic_helper_cleanup_planes(drm, state); |
| 66 | drm_atomic_state_free(state); | 66 | drm_atomic_state_put(state); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static void tegra_atomic_work(struct work_struct *work) | 69 | static void tegra_atomic_work(struct work_struct *work) |
| @@ -96,6 +96,7 @@ static int tegra_atomic_commit(struct drm_device *drm, | |||
| 96 | 96 | ||
| 97 | drm_atomic_helper_swap_state(state, true); | 97 | drm_atomic_helper_swap_state(state, true); |
| 98 | 98 | ||
| 99 | drm_atomic_state_get(state); | ||
| 99 | if (nonblock) | 100 | if (nonblock) |
| 100 | tegra_atomic_schedule(tegra, state); | 101 | tegra_atomic_schedule(tegra, state); |
| 101 | else | 102 | else |
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 52ebe8fc1784..822531ebd4b0 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c | |||
| @@ -72,16 +72,14 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) | |||
| 72 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); | 72 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
| 73 | struct drm_device *dev = crtc->dev; | 73 | struct drm_device *dev = crtc->dev; |
| 74 | struct drm_gem_cma_object *gem; | 74 | struct drm_gem_cma_object *gem; |
| 75 | unsigned int depth, bpp; | ||
| 76 | dma_addr_t start, end; | 75 | dma_addr_t start, end; |
| 77 | u64 dma_base_and_ceiling; | 76 | u64 dma_base_and_ceiling; |
| 78 | 77 | ||
| 79 | drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); | ||
| 80 | gem = drm_fb_cma_get_gem_obj(fb, 0); | 78 | gem = drm_fb_cma_get_gem_obj(fb, 0); |
| 81 | 79 | ||
| 82 | start = gem->paddr + fb->offsets[0] + | 80 | start = gem->paddr + fb->offsets[0] + |
| 83 | crtc->y * fb->pitches[0] + | 81 | crtc->y * fb->pitches[0] + |
| 84 | crtc->x * bpp / 8; | 82 | crtc->x * drm_format_plane_cpp(fb->pixel_format, 0); |
| 85 | 83 | ||
| 86 | end = start + (crtc->mode.vdisplay * fb->pitches[0]); | 84 | end = start + (crtc->mode.vdisplay * fb->pitches[0]); |
| 87 | 85 | ||
| @@ -461,16 +459,16 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
| 461 | if (info->tft_alt_mode) | 459 | if (info->tft_alt_mode) |
| 462 | reg |= LCDC_TFT_ALT_ENABLE; | 460 | reg |= LCDC_TFT_ALT_ENABLE; |
| 463 | if (priv->rev == 2) { | 461 | if (priv->rev == 2) { |
| 464 | unsigned int depth, bpp; | 462 | switch (fb->pixel_format) { |
| 465 | 463 | case DRM_FORMAT_BGR565: | |
| 466 | drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); | 464 | case DRM_FORMAT_RGB565: |
| 467 | switch (bpp) { | ||
| 468 | case 16: | ||
| 469 | break; | 465 | break; |
| 470 | case 32: | 466 | case DRM_FORMAT_XBGR8888: |
| 467 | case DRM_FORMAT_XRGB8888: | ||
| 471 | reg |= LCDC_V2_TFT_24BPP_UNPACK; | 468 | reg |= LCDC_V2_TFT_24BPP_UNPACK; |
| 472 | /* fallthrough */ | 469 | /* fallthrough */ |
| 473 | case 24: | 470 | case DRM_FORMAT_BGR888: |
| 471 | case DRM_FORMAT_RGB888: | ||
| 474 | reg |= LCDC_V2_TFT_24BPP_MODE; | 472 | reg |= LCDC_V2_TFT_24BPP_MODE; |
| 475 | break; | 473 | break; |
| 476 | default: | 474 | default: |
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index a694977c32f4..147fb28287ae 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c | |||
| @@ -143,8 +143,6 @@ static int tilcdc_commit(struct drm_device *dev, | |||
| 143 | 143 | ||
| 144 | drm_atomic_helper_cleanup_planes(dev, state); | 144 | drm_atomic_helper_cleanup_planes(dev, state); |
| 145 | 145 | ||
| 146 | drm_atomic_state_free(state); | ||
| 147 | |||
| 148 | return 0; | 146 | return 0; |
| 149 | } | 147 | } |
| 150 | 148 | ||
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index 74c65fa859b2..8a6a50d74aff 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c | |||
| @@ -39,7 +39,7 @@ static int tilcdc_plane_atomic_check(struct drm_plane *plane, | |||
| 39 | { | 39 | { |
| 40 | struct drm_crtc_state *crtc_state; | 40 | struct drm_crtc_state *crtc_state; |
| 41 | struct drm_plane_state *old_state = plane->state; | 41 | struct drm_plane_state *old_state = plane->state; |
| 42 | unsigned int depth, bpp; | 42 | unsigned int pitch; |
| 43 | 43 | ||
| 44 | if (!state->crtc) | 44 | if (!state->crtc) |
| 45 | return 0; | 45 | return 0; |
| @@ -68,8 +68,9 @@ static int tilcdc_plane_atomic_check(struct drm_plane *plane, | |||
| 68 | return -EINVAL; | 68 | return -EINVAL; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | drm_fb_get_bpp_depth(state->fb->pixel_format, &depth, &bpp); | 71 | pitch = crtc_state->mode.hdisplay * |
| 72 | if (state->fb->pitches[0] != crtc_state->mode.hdisplay * bpp / 8) { | 72 | drm_format_plane_cpp(state->fb->pixel_format, 0); |
| 73 | if (state->fb->pitches[0] != pitch) { | ||
| 73 | dev_err(plane->dev->dev, | 74 | dev_err(plane->dev->dev, |
| 74 | "Invalid pitch: fb and crtc widths must be the same"); | 75 | "Invalid pitch: fb and crtc widths must be the same"); |
| 75 | return -EINVAL; | 76 | return -EINVAL; |
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index c1f65c6c8e60..f31f72af8551 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c | |||
| @@ -61,7 +61,7 @@ vc4_atomic_complete_commit(struct vc4_commit *c) | |||
| 61 | 61 | ||
| 62 | drm_atomic_helper_cleanup_planes(dev, state); | 62 | drm_atomic_helper_cleanup_planes(dev, state); |
| 63 | 63 | ||
| 64 | drm_atomic_state_free(state); | 64 | drm_atomic_state_put(state); |
| 65 | 65 | ||
| 66 | up(&vc4->async_modeset); | 66 | up(&vc4->async_modeset); |
| 67 | 67 | ||
| @@ -173,6 +173,7 @@ static int vc4_atomic_commit(struct drm_device *dev, | |||
| 173 | * current layout. | 173 | * current layout. |
| 174 | */ | 174 | */ |
| 175 | 175 | ||
| 176 | drm_atomic_state_get(state); | ||
| 176 | if (nonblock) { | 177 | if (nonblock) { |
| 177 | vc4_queue_seqno_cb(dev, &c->cb, wait_seqno, | 178 | vc4_queue_seqno_cb(dev, &c->cb, wait_seqno, |
| 178 | vc4_atomic_complete_commit_seqno_cb); | 179 | vc4_atomic_complete_commit_seqno_cb); |
diff --git a/drivers/gpu/drm/virtio/Kconfig b/drivers/gpu/drm/virtio/Kconfig index e1afc3d3f8d9..81d1807ac228 100644 --- a/drivers/gpu/drm/virtio/Kconfig +++ b/drivers/gpu/drm/virtio/Kconfig | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | config DRM_VIRTIO_GPU | 1 | config DRM_VIRTIO_GPU |
| 2 | tristate "Virtio GPU driver" | 2 | tristate "Virtio GPU driver" |
| 3 | depends on DRM && VIRTIO | 3 | depends on DRM && VIRTIO |
| 4 | select DRM_KMS_HELPER | 4 | select DRM_KMS_HELPER |
| 5 | select DRM_TTM | 5 | select DRM_TTM |
| 6 | help | 6 | help |
| 7 | This is the virtual GPU driver for virtio. It can be used with | 7 | This is the virtual GPU driver for virtio. It can be used with |
| 8 | QEMU based VMMs (like KVM or Xen). | 8 | QEMU based VMMs (like KVM or Xen). |
| 9 | 9 | ||
| 10 | If unsure say M. | 10 | If unsure say M. |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index bf28ccc150df..c965514b82be 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
| @@ -980,14 +980,22 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, | |||
| 980 | struct vmw_dma_buffer *bo = NULL; | 980 | struct vmw_dma_buffer *bo = NULL; |
| 981 | struct ttm_base_object *user_obj; | 981 | struct ttm_base_object *user_obj; |
| 982 | struct drm_mode_fb_cmd mode_cmd; | 982 | struct drm_mode_fb_cmd mode_cmd; |
| 983 | const struct drm_format_info *info; | ||
| 983 | int ret; | 984 | int ret; |
| 984 | 985 | ||
| 986 | info = drm_format_info(mode_cmd2->pixel_format); | ||
| 987 | if (!info || !info->depth) { | ||
| 988 | DRM_ERROR("Unsupported framebuffer format %s\n", | ||
| 989 | drm_get_format_name(mode_cmd2->pixel_format)); | ||
| 990 | return ERR_PTR(-EINVAL); | ||
| 991 | } | ||
| 992 | |||
| 985 | mode_cmd.width = mode_cmd2->width; | 993 | mode_cmd.width = mode_cmd2->width; |
| 986 | mode_cmd.height = mode_cmd2->height; | 994 | mode_cmd.height = mode_cmd2->height; |
| 987 | mode_cmd.pitch = mode_cmd2->pitches[0]; | 995 | mode_cmd.pitch = mode_cmd2->pitches[0]; |
| 988 | mode_cmd.handle = mode_cmd2->handles[0]; | 996 | mode_cmd.handle = mode_cmd2->handles[0]; |
| 989 | drm_fb_get_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth, | 997 | mode_cmd.depth = info->depth; |
| 990 | &mode_cmd.bpp); | 998 | mode_cmd.bpp = info->cpp[0] * 8; |
| 991 | 999 | ||
| 992 | /** | 1000 | /** |
| 993 | * This code should be conditioned on Screen Objects not being used. | 1001 | * This code should be conditioned on Screen Objects not being used. |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 52ca1c9d070e..1a85fb2d4dc6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | |||
| @@ -575,7 +575,7 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo, | |||
| 575 | long lret; | 575 | long lret; |
| 576 | 576 | ||
| 577 | lret = reservation_object_wait_timeout_rcu(bo->resv, true, true, | 577 | lret = reservation_object_wait_timeout_rcu(bo->resv, true, true, |
| 578 | nonblock ? 0 : MAX_SCHEDULE_TIMEOUT); | 578 | nonblock ? 0 : MAX_SCHEDULE_TIMEOUT); |
| 579 | if (!lret) | 579 | if (!lret) |
| 580 | return -EBUSY; | 580 | return -EBUSY; |
| 581 | else if (lret < 0) | 581 | else if (lret < 0) |
diff --git a/drivers/gpu/ipu-v3/Kconfig b/drivers/gpu/ipu-v3/Kconfig index aefdff95356d..08766c6e7856 100644 --- a/drivers/gpu/ipu-v3/Kconfig +++ b/drivers/gpu/ipu-v3/Kconfig | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | config IMX_IPUV3_CORE | 1 | config IMX_IPUV3_CORE |
| 2 | tristate "IPUv3 core support" | 2 | tristate "IPUv3 core support" |
| 3 | depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM | 3 | depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM |
| 4 | depends on RESET_CONTROLLER | ||
| 5 | select GENERIC_IRQ_CHIP | 4 | select GENERIC_IRQ_CHIP |
| 6 | help | 5 | help |
| 7 | Choose this if you have a i.MX5/6 system and want to use the Image | 6 | Choose this if you have a i.MX5/6 system and want to use the Image |
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index 1887f199ccb7..77657a8c0cd4 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c | |||
| @@ -1022,21 +1022,16 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf, | |||
| 1022 | 1022 | ||
| 1023 | unsigned int io_state; | 1023 | unsigned int io_state; |
| 1024 | 1024 | ||
| 1025 | char *kbuf, *curr_pos; | 1025 | char kbuf[64], *curr_pos; |
| 1026 | size_t remaining = count; | 1026 | size_t remaining = count; |
| 1027 | 1027 | ||
| 1028 | int ret_val; | 1028 | int ret_val; |
| 1029 | int i; | 1029 | int i; |
| 1030 | 1030 | ||
| 1031 | 1031 | if (count >= sizeof(kbuf)) | |
| 1032 | kbuf = kmalloc(count + 1, GFP_KERNEL); | 1032 | return -EINVAL; |
| 1033 | if (!kbuf) | 1033 | if (copy_from_user(kbuf, buf, count)) |
| 1034 | return -ENOMEM; | ||
| 1035 | |||
| 1036 | if (copy_from_user(kbuf, buf, count)) { | ||
| 1037 | kfree(kbuf); | ||
| 1038 | return -EFAULT; | 1034 | return -EFAULT; |
| 1039 | } | ||
| 1040 | curr_pos = kbuf; | 1035 | curr_pos = kbuf; |
| 1041 | kbuf[count] = '\0'; /* Just to make sure... */ | 1036 | kbuf[count] = '\0'; /* Just to make sure... */ |
| 1042 | 1037 | ||
| @@ -1259,11 +1254,9 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf, | |||
| 1259 | goto done; | 1254 | goto done; |
| 1260 | } | 1255 | } |
| 1261 | /* If we got here, the message written is not part of the protocol! */ | 1256 | /* If we got here, the message written is not part of the protocol! */ |
| 1262 | kfree(kbuf); | ||
| 1263 | return -EPROTO; | 1257 | return -EPROTO; |
| 1264 | 1258 | ||
| 1265 | done: | 1259 | done: |
| 1266 | kfree(kbuf); | ||
| 1267 | return ret_val; | 1260 | return ret_val; |
| 1268 | } | 1261 | } |
| 1269 | 1262 | ||
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index 162689227a23..1cf907ecded4 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c | |||
| @@ -533,6 +533,10 @@ hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect) | |||
| 533 | return "4:3"; | 533 | return "4:3"; |
| 534 | case HDMI_PICTURE_ASPECT_16_9: | 534 | case HDMI_PICTURE_ASPECT_16_9: |
| 535 | return "16:9"; | 535 | return "16:9"; |
| 536 | case HDMI_PICTURE_ASPECT_64_27: | ||
| 537 | return "64:27"; | ||
| 538 | case HDMI_PICTURE_ASPECT_256_135: | ||
| 539 | return "256:135"; | ||
| 536 | case HDMI_PICTURE_ASPECT_RESERVED: | 540 | case HDMI_PICTURE_ASPECT_RESERVED: |
| 537 | return "Reserved"; | 541 | return "Reserved"; |
| 538 | } | 542 | } |
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 9701f2dfb784..fc8af53b18aa 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h | |||
| @@ -153,6 +153,7 @@ struct __drm_connnectors_state { | |||
| 153 | 153 | ||
| 154 | /** | 154 | /** |
| 155 | * struct drm_atomic_state - the global state object for atomic updates | 155 | * struct drm_atomic_state - the global state object for atomic updates |
| 156 | * @ref: count of all references to this state (will not be freed until zero) | ||
| 156 | * @dev: parent DRM device | 157 | * @dev: parent DRM device |
| 157 | * @allow_modeset: allow full modeset | 158 | * @allow_modeset: allow full modeset |
| 158 | * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics | 159 | * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics |
| @@ -164,6 +165,8 @@ struct __drm_connnectors_state { | |||
| 164 | * @acquire_ctx: acquire context for this atomic modeset state update | 165 | * @acquire_ctx: acquire context for this atomic modeset state update |
| 165 | */ | 166 | */ |
| 166 | struct drm_atomic_state { | 167 | struct drm_atomic_state { |
| 168 | struct kref ref; | ||
| 169 | |||
| 167 | struct drm_device *dev; | 170 | struct drm_device *dev; |
| 168 | bool allow_modeset : 1; | 171 | bool allow_modeset : 1; |
| 169 | bool legacy_cursor_update : 1; | 172 | bool legacy_cursor_update : 1; |
| @@ -193,7 +196,33 @@ static inline void drm_crtc_commit_get(struct drm_crtc_commit *commit) | |||
| 193 | struct drm_atomic_state * __must_check | 196 | struct drm_atomic_state * __must_check |
| 194 | drm_atomic_state_alloc(struct drm_device *dev); | 197 | drm_atomic_state_alloc(struct drm_device *dev); |
| 195 | void drm_atomic_state_clear(struct drm_atomic_state *state); | 198 | void drm_atomic_state_clear(struct drm_atomic_state *state); |
| 196 | void drm_atomic_state_free(struct drm_atomic_state *state); | 199 | |
| 200 | /** | ||
| 201 | * drm_atomic_state_get - acquire a reference to the atomic state | ||
| 202 | * @state: The atomic state | ||
| 203 | * | ||
| 204 | * Returns a new reference to the @state | ||
| 205 | */ | ||
| 206 | static inline struct drm_atomic_state * | ||
| 207 | drm_atomic_state_get(struct drm_atomic_state *state) | ||
| 208 | { | ||
| 209 | kref_get(&state->ref); | ||
| 210 | return state; | ||
| 211 | } | ||
| 212 | |||
| 213 | void __drm_atomic_state_free(struct kref *ref); | ||
| 214 | |||
| 215 | /** | ||
| 216 | * drm_atomic_state_put - release a reference to the atomic state | ||
| 217 | * @state: The atomic state | ||
| 218 | * | ||
| 219 | * This releases a reference to @state which is freed after removing the | ||
| 220 | * final reference. No locking required and callable from any context. | ||
| 221 | */ | ||
| 222 | static inline void drm_atomic_state_put(struct drm_atomic_state *state) | ||
| 223 | { | ||
| 224 | kref_put(&state->ref, __drm_atomic_state_free); | ||
| 225 | } | ||
| 197 | 226 | ||
| 198 | int __must_check | 227 | int __must_check |
| 199 | drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state); | 228 | drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state); |
| @@ -365,8 +394,17 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); | |||
| 365 | * | 394 | * |
| 366 | * To give drivers flexibility struct &drm_crtc_state has 3 booleans to track | 395 | * To give drivers flexibility struct &drm_crtc_state has 3 booleans to track |
| 367 | * whether the state CRTC changed enough to need a full modeset cycle: | 396 | * whether the state CRTC changed enough to need a full modeset cycle: |
| 368 | * connectors_changed, mode_changed and active_change. This helper simply | 397 | * connectors_changed, mode_changed and active_changed. This helper simply |
| 369 | * combines these three to compute the overall need for a modeset for @state. | 398 | * combines these three to compute the overall need for a modeset for @state. |
| 399 | * | ||
| 400 | * The atomic helper code sets these booleans, but drivers can and should | ||
| 401 | * change them appropriately to accurately represent whether a modeset is | ||
| 402 | * really needed. In general, drivers should avoid full modesets whenever | ||
| 403 | * possible. | ||
| 404 | * | ||
| 405 | * For example if the CRTC mode has changed, and the hardware is able to enact | ||
| 406 | * the requested mode change without going through a full modeset, the driver | ||
| 407 | * should clear mode_changed during its ->atomic_check. | ||
| 370 | */ | 408 | */ |
| 371 | static inline bool | 409 | static inline bool |
| 372 | drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state) | 410 | drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state) |
diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h index 36baa175de99..fd351924e1c5 100644 --- a/include/drm/drm_blend.h +++ b/include/drm/drm_blend.h | |||
| @@ -47,8 +47,16 @@ struct drm_atomic_state; | |||
| 47 | #define DRM_REFLECT_Y BIT(5) | 47 | #define DRM_REFLECT_Y BIT(5) |
| 48 | #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y) | 48 | #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y) |
| 49 | 49 | ||
| 50 | static inline bool drm_rotation_90_or_270(unsigned int rotation) | ||
| 51 | { | ||
| 52 | return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270); | ||
| 53 | } | ||
| 54 | |||
| 50 | struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, | 55 | struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, |
| 51 | unsigned int supported_rotations); | 56 | unsigned int supported_rotations); |
| 57 | int drm_plane_create_rotation_property(struct drm_plane *plane, | ||
| 58 | unsigned int rotation, | ||
| 59 | unsigned int supported_rotations); | ||
| 52 | unsigned int drm_rotation_simplify(unsigned int rotation, | 60 | unsigned int drm_rotation_simplify(unsigned int rotation, |
| 53 | unsigned int supported_rotations); | 61 | unsigned int supported_rotations); |
| 54 | 62 | ||
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 0aa292526567..284c1b3aec10 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <drm/drm_plane.h> | 47 | #include <drm/drm_plane.h> |
| 48 | #include <drm/drm_blend.h> | 48 | #include <drm/drm_blend.h> |
| 49 | #include <drm/drm_color_mgmt.h> | 49 | #include <drm/drm_color_mgmt.h> |
| 50 | #include <drm/drm_debugfs_crc.h> | ||
| 50 | 51 | ||
| 51 | struct drm_device; | 52 | struct drm_device; |
| 52 | struct drm_mode_set; | 53 | struct drm_mode_set; |
| @@ -116,6 +117,11 @@ struct drm_plane_helper_funcs; | |||
| 116 | * never return in a failure from the ->atomic_check callback. Userspace assumes | 117 | * never return in a failure from the ->atomic_check callback. Userspace assumes |
| 117 | * that a DPMS On will always succeed. In other words: @enable controls resource | 118 | * that a DPMS On will always succeed. In other words: @enable controls resource |
| 118 | * assignment, @active controls the actual hardware state. | 119 | * assignment, @active controls the actual hardware state. |
| 120 | * | ||
| 121 | * The three booleans active_changed, connectors_changed and mode_changed are | ||
| 122 | * intended to indicate whether a full modeset is needed, rather than strictly | ||
| 123 | * describing what has changed in a commit. | ||
| 124 | * See also: drm_atomic_crtc_needs_modeset() | ||
| 119 | */ | 125 | */ |
| 120 | struct drm_crtc_state { | 126 | struct drm_crtc_state { |
| 121 | struct drm_crtc *crtc; | 127 | struct drm_crtc *crtc; |
| @@ -564,6 +570,30 @@ struct drm_crtc_funcs { | |||
| 564 | * before data structures are torndown. | 570 | * before data structures are torndown. |
| 565 | */ | 571 | */ |
| 566 | void (*early_unregister)(struct drm_crtc *crtc); | 572 | void (*early_unregister)(struct drm_crtc *crtc); |
| 573 | |||
| 574 | /** | ||
| 575 | * @set_crc_source: | ||
| 576 | * | ||
| 577 | * Changes the source of CRC checksums of frames at the request of | ||
| 578 | * userspace, typically for testing purposes. The sources available are | ||
| 579 | * specific of each driver and a %NULL value indicates that CRC | ||
| 580 | * generation is to be switched off. | ||
| 581 | * | ||
| 582 | * When CRC generation is enabled, the driver should call | ||
| 583 | * drm_crtc_add_crc_entry() at each frame, providing any information | ||
| 584 | * that characterizes the frame contents in the crcN arguments, as | ||
| 585 | * provided from the configured source. Drivers must accept a "auto" | ||
| 586 | * source name that will select a default source for this CRTC. | ||
| 587 | * | ||
| 588 | * This callback is optional if the driver does not support any CRC | ||
| 589 | * generation functionality. | ||
| 590 | * | ||
| 591 | * RETURNS: | ||
| 592 | * | ||
| 593 | * 0 on success or a negative error code on failure. | ||
| 594 | */ | ||
| 595 | int (*set_crc_source)(struct drm_crtc *crtc, const char *source, | ||
| 596 | size_t *values_cnt); | ||
| 567 | }; | 597 | }; |
| 568 | 598 | ||
| 569 | /** | 599 | /** |
| @@ -680,6 +710,22 @@ struct drm_crtc { | |||
| 680 | * context. | 710 | * context. |
| 681 | */ | 711 | */ |
| 682 | struct drm_modeset_acquire_ctx *acquire_ctx; | 712 | struct drm_modeset_acquire_ctx *acquire_ctx; |
| 713 | |||
| 714 | #ifdef CONFIG_DEBUG_FS | ||
| 715 | /** | ||
| 716 | * @debugfs_entry: | ||
| 717 | * | ||
| 718 | * Debugfs directory for this CRTC. | ||
| 719 | */ | ||
| 720 | struct dentry *debugfs_entry; | ||
| 721 | |||
| 722 | /** | ||
| 723 | * @crc: | ||
| 724 | * | ||
| 725 | * Configuration settings of CRC capture. | ||
| 726 | */ | ||
| 727 | struct drm_crtc_crc crc; | ||
| 728 | #endif | ||
| 683 | }; | 729 | }; |
| 684 | 730 | ||
| 685 | /** | 731 | /** |
| @@ -1354,7 +1400,7 @@ static inline unsigned int drm_crtc_index(const struct drm_crtc *crtc) | |||
| 1354 | * Given a registered CRTC, return the mask bit of that CRTC for an | 1400 | * Given a registered CRTC, return the mask bit of that CRTC for an |
| 1355 | * encoder's possible_crtcs field. | 1401 | * encoder's possible_crtcs field. |
| 1356 | */ | 1402 | */ |
| 1357 | static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc) | 1403 | static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc) |
| 1358 | { | 1404 | { |
| 1359 | return 1 << drm_crtc_index(crtc); | 1405 | return 1 << drm_crtc_index(crtc); |
| 1360 | } | 1406 | } |
diff --git a/include/drm/drm_debugfs_crc.h b/include/drm/drm_debugfs_crc.h new file mode 100644 index 000000000000..7d63b1d4adb9 --- /dev/null +++ b/include/drm/drm_debugfs_crc.h | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2016 Collabora Ltd. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | */ | ||
| 22 | #ifndef __DRM_DEBUGFS_CRC_H__ | ||
| 23 | #define __DRM_DEBUGFS_CRC_H__ | ||
| 24 | |||
| 25 | #define DRM_MAX_CRC_NR 10 | ||
| 26 | |||
| 27 | /** | ||
| 28 | * struct drm_crtc_crc_entry - entry describing a frame's content | ||
| 29 | * @has_frame_counter: whether the source was able to provide a frame number | ||
| 30 | * @frame: number of the frame this CRC is about, if @has_frame_counter is true | ||
| 31 | * @crc: array of values that characterize the frame | ||
| 32 | */ | ||
| 33 | struct drm_crtc_crc_entry { | ||
| 34 | bool has_frame_counter; | ||
| 35 | uint32_t frame; | ||
| 36 | uint32_t crcs[DRM_MAX_CRC_NR]; | ||
| 37 | }; | ||
| 38 | |||
| 39 | #define DRM_CRC_ENTRIES_NR 128 | ||
| 40 | |||
| 41 | /** | ||
| 42 | * struct drm_crtc_crc - data supporting CRC capture on a given CRTC | ||
| 43 | * @lock: protects the fields in this struct | ||
| 44 | * @source: name of the currently configured source of CRCs | ||
| 45 | * @opened: whether userspace has opened the data file for reading | ||
| 46 | * @entries: array of entries, with size of %DRM_CRC_ENTRIES_NR | ||
| 47 | * @head: head of circular queue | ||
| 48 | * @tail: tail of circular queue | ||
| 49 | * @values_cnt: number of CRC values per entry, up to %DRM_MAX_CRC_NR | ||
| 50 | * @wq: workqueue used to synchronize reading and writing | ||
| 51 | */ | ||
| 52 | struct drm_crtc_crc { | ||
| 53 | spinlock_t lock; | ||
| 54 | const char *source; | ||
| 55 | bool opened; | ||
| 56 | struct drm_crtc_crc_entry *entries; | ||
| 57 | int head, tail; | ||
| 58 | size_t values_cnt; | ||
| 59 | wait_queue_head_t wq; | ||
| 60 | }; | ||
| 61 | |||
| 62 | #if defined(CONFIG_DEBUG_FS) | ||
| 63 | int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, | ||
| 64 | uint32_t frame, uint32_t *crcs); | ||
| 65 | #else | ||
| 66 | static inline int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, | ||
| 67 | uint32_t frame, uint32_t *crcs) | ||
| 68 | { | ||
| 69 | return -EINVAL; | ||
| 70 | } | ||
| 71 | #endif /* defined(CONFIG_DEBUG_FS) */ | ||
| 72 | |||
| 73 | #endif /* __DRM_DEBUGFS_CRC_H__ */ | ||
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h index 387e33a4d6ee..c7438ff0d609 100644 --- a/include/drm/drm_encoder.h +++ b/include/drm/drm_encoder.h | |||
| @@ -189,7 +189,7 @@ static inline unsigned int drm_encoder_index(struct drm_encoder *encoder) | |||
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | /* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */ | 191 | /* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */ |
| 192 | static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc); | 192 | static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc); |
| 193 | 193 | ||
| 194 | /** | 194 | /** |
| 195 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? | 195 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? |
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 30c30fa87ee8..dc0aafab9ffd 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h | |||
| @@ -25,8 +25,29 @@ | |||
| 25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
| 26 | #include <uapi/drm/drm_fourcc.h> | 26 | #include <uapi/drm/drm_fourcc.h> |
| 27 | 27 | ||
| 28 | /** | ||
| 29 | * struct drm_format_info - information about a DRM format | ||
| 30 | * @format: 4CC format identifier (DRM_FORMAT_*) | ||
| 31 | * @depth: Color depth (number of bits per pixel excluding padding bits), | ||
| 32 | * valid for a subset of RGB formats only. This is a legacy field, do not | ||
| 33 | * use in new code and set to 0 for new formats. | ||
| 34 | * @num_planes: Number of color planes (1 to 3) | ||
| 35 | * @cpp: Number of bytes per pixel (per plane) | ||
| 36 | * @hsub: Horizontal chroma subsampling factor | ||
| 37 | * @vsub: Vertical chroma subsampling factor | ||
| 38 | */ | ||
| 39 | struct drm_format_info { | ||
| 40 | u32 format; | ||
| 41 | u8 depth; | ||
| 42 | u8 num_planes; | ||
| 43 | u8 cpp[3]; | ||
| 44 | u8 hsub; | ||
| 45 | u8 vsub; | ||
| 46 | }; | ||
| 47 | |||
| 48 | const struct drm_format_info *__drm_format_info(u32 format); | ||
| 49 | const struct drm_format_info *drm_format_info(u32 format); | ||
| 28 | uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); | 50 | uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); |
| 29 | void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); | ||
| 30 | int drm_format_num_planes(uint32_t format); | 51 | int drm_format_num_planes(uint32_t format); |
| 31 | int drm_format_plane_cpp(uint32_t format, int plane); | 52 | int drm_format_plane_cpp(uint32_t format, int plane); |
| 32 | int drm_format_horz_chroma_subsampling(uint32_t format); | 53 | int drm_format_horz_chroma_subsampling(uint32_t format); |
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 43cf193e54d6..98b39d66eb32 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h | |||
| @@ -88,7 +88,6 @@ struct drm_plane_state { | |||
| 88 | struct drm_atomic_state *state; | 88 | struct drm_atomic_state *state; |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | |||
| 92 | /** | 91 | /** |
| 93 | * struct drm_plane_funcs - driver plane control functions | 92 | * struct drm_plane_funcs - driver plane control functions |
| 94 | */ | 93 | */ |
| @@ -386,6 +385,7 @@ enum drm_plane_type { | |||
| 386 | * @type: type of plane (overlay, primary, cursor) | 385 | * @type: type of plane (overlay, primary, cursor) |
| 387 | * @state: current atomic state for this plane | 386 | * @state: current atomic state for this plane |
| 388 | * @zpos_property: zpos property for this plane | 387 | * @zpos_property: zpos property for this plane |
| 388 | * @rotation_property: rotation property for this plane | ||
| 389 | * @helper_private: mid-layer private data | 389 | * @helper_private: mid-layer private data |
| 390 | */ | 390 | */ |
| 391 | struct drm_plane { | 391 | struct drm_plane { |
| @@ -432,6 +432,7 @@ struct drm_plane { | |||
| 432 | struct drm_plane_state *state; | 432 | struct drm_plane_state *state; |
| 433 | 433 | ||
| 434 | struct drm_property *zpos_property; | 434 | struct drm_property *zpos_property; |
| 435 | struct drm_property *rotation_property; | ||
| 435 | }; | 436 | }; |
| 436 | 437 | ||
| 437 | #define obj_to_plane(x) container_of(x, struct drm_plane, base) | 438 | #define obj_to_plane(x) container_of(x, struct drm_plane, base) |
diff --git a/include/linux/fence.h b/include/linux/fence.h index 0d763053f97a..c9c5ba98c302 100644 --- a/include/linux/fence.h +++ b/include/linux/fence.h | |||
| @@ -183,6 +183,16 @@ void fence_release(struct kref *kref); | |||
| 183 | void fence_free(struct fence *fence); | 183 | void fence_free(struct fence *fence); |
| 184 | 184 | ||
| 185 | /** | 185 | /** |
| 186 | * fence_put - decreases refcount of the fence | ||
| 187 | * @fence: [in] fence to reduce refcount of | ||
| 188 | */ | ||
| 189 | static inline void fence_put(struct fence *fence) | ||
| 190 | { | ||
| 191 | if (fence) | ||
| 192 | kref_put(&fence->refcount, fence_release); | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 186 | * fence_get - increases refcount of the fence | 196 | * fence_get - increases refcount of the fence |
| 187 | * @fence: [in] fence to increase refcount of | 197 | * @fence: [in] fence to increase refcount of |
| 188 | * | 198 | * |
| @@ -210,13 +220,49 @@ static inline struct fence *fence_get_rcu(struct fence *fence) | |||
| 210 | } | 220 | } |
| 211 | 221 | ||
| 212 | /** | 222 | /** |
| 213 | * fence_put - decreases refcount of the fence | 223 | * fence_get_rcu_safe - acquire a reference to an RCU tracked fence |
| 214 | * @fence: [in] fence to reduce refcount of | 224 | * @fence: [in] pointer to fence to increase refcount of |
| 225 | * | ||
| 226 | * Function returns NULL if no refcount could be obtained, or the fence. | ||
| 227 | * This function handles acquiring a reference to a fence that may be | ||
| 228 | * reallocated within the RCU grace period (such as with SLAB_DESTROY_BY_RCU), | ||
| 229 | * so long as the caller is using RCU on the pointer to the fence. | ||
| 230 | * | ||
| 231 | * An alternative mechanism is to employ a seqlock to protect a bunch of | ||
| 232 | * fences, such as used by struct reservation_object. When using a seqlock, | ||
| 233 | * the seqlock must be taken before and checked after a reference to the | ||
| 234 | * fence is acquired (as shown here). | ||
| 235 | * | ||
| 236 | * The caller is required to hold the RCU read lock. | ||
| 215 | */ | 237 | */ |
| 216 | static inline void fence_put(struct fence *fence) | 238 | static inline struct fence *fence_get_rcu_safe(struct fence * __rcu *fencep) |
| 217 | { | 239 | { |
| 218 | if (fence) | 240 | do { |
| 219 | kref_put(&fence->refcount, fence_release); | 241 | struct fence *fence; |
| 242 | |||
| 243 | fence = rcu_dereference(*fencep); | ||
| 244 | if (!fence || !fence_get_rcu(fence)) | ||
| 245 | return NULL; | ||
| 246 | |||
| 247 | /* The atomic_inc_not_zero() inside fence_get_rcu() | ||
| 248 | * provides a full memory barrier upon success (such as now). | ||
| 249 | * This is paired with the write barrier from assigning | ||
| 250 | * to the __rcu protected fence pointer so that if that | ||
| 251 | * pointer still matches the current fence, we know we | ||
| 252 | * have successfully acquire a reference to it. If it no | ||
| 253 | * longer matches, we are holding a reference to some other | ||
| 254 | * reallocated pointer. This is possible if the allocator | ||
| 255 | * is using a freelist like SLAB_DESTROY_BY_RCU where the | ||
| 256 | * fence remains valid for the RCU grace period, but it | ||
| 257 | * may be reallocated. When using such allocators, we are | ||
| 258 | * responsible for ensuring the reference we get is to | ||
| 259 | * the right fence, as below. | ||
| 260 | */ | ||
| 261 | if (fence == rcu_access_pointer(*fencep)) | ||
| 262 | return rcu_pointer_handoff(fence); | ||
| 263 | |||
| 264 | fence_put(fence); | ||
| 265 | } while (1); | ||
| 220 | } | 266 | } |
| 221 | 267 | ||
| 222 | int fence_signal(struct fence *fence); | 268 | int fence_signal(struct fence *fence); |
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index e9744202fa29..edbb4fc674ed 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h | |||
| @@ -78,6 +78,8 @@ enum hdmi_picture_aspect { | |||
| 78 | HDMI_PICTURE_ASPECT_NONE, | 78 | HDMI_PICTURE_ASPECT_NONE, |
| 79 | HDMI_PICTURE_ASPECT_4_3, | 79 | HDMI_PICTURE_ASPECT_4_3, |
| 80 | HDMI_PICTURE_ASPECT_16_9, | 80 | HDMI_PICTURE_ASPECT_16_9, |
| 81 | HDMI_PICTURE_ASPECT_64_27, | ||
| 82 | HDMI_PICTURE_ASPECT_256_135, | ||
| 81 | HDMI_PICTURE_ASPECT_RESERVED, | 83 | HDMI_PICTURE_ASPECT_RESERVED, |
| 82 | }; | 84 | }; |
| 83 | 85 | ||
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index df0e3504c349..084b50a02dc5 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h | |||
| @@ -77,6 +77,25 @@ extern "C" { | |||
| 77 | #define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) | 77 | #define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) |
| 78 | #define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) | 78 | #define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) |
| 79 | 79 | ||
| 80 | /* Picture aspect ratio options */ | ||
| 81 | #define DRM_MODE_PICTURE_ASPECT_NONE 0 | ||
| 82 | #define DRM_MODE_PICTURE_ASPECT_4_3 1 | ||
| 83 | #define DRM_MODE_PICTURE_ASPECT_16_9 2 | ||
| 84 | #define DRM_MODE_PICTURE_ASPECT_64_27 3 | ||
| 85 | #define DRM_MODE_PICTURE_ASPECT_256_135 4 | ||
| 86 | |||
| 87 | /* Aspect ratio flag bitmask (4 bits 22:19) */ | ||
| 88 | #define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) | ||
| 89 | #define DRM_MODE_FLAG_PIC_AR_NONE \ | ||
| 90 | (DRM_MODE_PICTURE_ASPECT_NONE<<19) | ||
| 91 | #define DRM_MODE_FLAG_PIC_AR_4_3 \ | ||
| 92 | (DRM_MODE_PICTURE_ASPECT_4_3<<19) | ||
| 93 | #define DRM_MODE_FLAG_PIC_AR_16_9 \ | ||
| 94 | (DRM_MODE_PICTURE_ASPECT_16_9<<19) | ||
| 95 | #define DRM_MODE_FLAG_PIC_AR_64_27 \ | ||
| 96 | (DRM_MODE_PICTURE_ASPECT_64_27<<19) | ||
| 97 | #define DRM_MODE_FLAG_PIC_AR_256_135 \ | ||
| 98 | (DRM_MODE_PICTURE_ASPECT_256_135<<19) | ||
| 80 | 99 | ||
| 81 | /* DPMS flags */ | 100 | /* DPMS flags */ |
| 82 | /* bit compatible with the xorg definitions. */ | 101 | /* bit compatible with the xorg definitions. */ |
| @@ -92,11 +111,6 @@ extern "C" { | |||
| 92 | #define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ | 111 | #define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ |
| 93 | #define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ | 112 | #define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ |
| 94 | 113 | ||
| 95 | /* Picture aspect ratio options */ | ||
| 96 | #define DRM_MODE_PICTURE_ASPECT_NONE 0 | ||
| 97 | #define DRM_MODE_PICTURE_ASPECT_4_3 1 | ||
| 98 | #define DRM_MODE_PICTURE_ASPECT_16_9 2 | ||
| 99 | |||
| 100 | /* Dithering mode options */ | 114 | /* Dithering mode options */ |
| 101 | #define DRM_MODE_DITHERING_OFF 0 | 115 | #define DRM_MODE_DITHERING_OFF 0 |
| 102 | #define DRM_MODE_DITHERING_ON 1 | 116 | #define DRM_MODE_DITHERING_ON 1 |
