0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include <linux/ctype.h>
0033 #include <linux/list.h>
0034 #include <linux/slab.h>
0035 #include <linux/export.h>
0036 #include <linux/dma-fence.h>
0037 #include <linux/uaccess.h>
0038 #include <drm/drm_blend.h>
0039 #include <drm/drm_crtc.h>
0040 #include <drm/drm_edid.h>
0041 #include <drm/drm_fourcc.h>
0042 #include <drm/drm_framebuffer.h>
0043 #include <drm/drm_managed.h>
0044 #include <drm/drm_modeset_lock.h>
0045 #include <drm/drm_atomic.h>
0046 #include <drm/drm_auth.h>
0047 #include <drm/drm_debugfs_crc.h>
0048 #include <drm/drm_drv.h>
0049 #include <drm/drm_print.h>
0050 #include <drm/drm_file.h>
0051
0052 #include "drm_crtc_internal.h"
0053 #include "drm_internal.h"
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)
0088 {
0089 struct drm_crtc *crtc;
0090
0091 drm_for_each_crtc(crtc, dev)
0092 if (idx == crtc->index)
0093 return crtc;
0094
0095 return NULL;
0096 }
0097 EXPORT_SYMBOL(drm_crtc_from_index);
0098
0099 int drm_crtc_force_disable(struct drm_crtc *crtc)
0100 {
0101 struct drm_mode_set set = {
0102 .crtc = crtc,
0103 };
0104
0105 WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
0106
0107 return drm_mode_set_config_internal(&set);
0108 }
0109
0110 static unsigned int drm_num_crtcs(struct drm_device *dev)
0111 {
0112 unsigned int num = 0;
0113 struct drm_crtc *tmp;
0114
0115 drm_for_each_crtc(tmp, dev) {
0116 num++;
0117 }
0118
0119 return num;
0120 }
0121
0122 int drm_crtc_register_all(struct drm_device *dev)
0123 {
0124 struct drm_crtc *crtc;
0125 int ret = 0;
0126
0127 drm_for_each_crtc(crtc, dev) {
0128 drm_debugfs_crtc_add(crtc);
0129
0130 if (crtc->funcs->late_register)
0131 ret = crtc->funcs->late_register(crtc);
0132 if (ret)
0133 return ret;
0134 }
0135
0136 return 0;
0137 }
0138
0139 void drm_crtc_unregister_all(struct drm_device *dev)
0140 {
0141 struct drm_crtc *crtc;
0142
0143 drm_for_each_crtc(crtc, dev) {
0144 if (crtc->funcs->early_unregister)
0145 crtc->funcs->early_unregister(crtc);
0146 drm_debugfs_crtc_remove(crtc);
0147 }
0148 }
0149
0150 static int drm_crtc_crc_init(struct drm_crtc *crtc)
0151 {
0152 #ifdef CONFIG_DEBUG_FS
0153 spin_lock_init(&crtc->crc.lock);
0154 init_waitqueue_head(&crtc->crc.wq);
0155 crtc->crc.source = kstrdup("auto", GFP_KERNEL);
0156 if (!crtc->crc.source)
0157 return -ENOMEM;
0158 #endif
0159 return 0;
0160 }
0161
0162 static void drm_crtc_crc_fini(struct drm_crtc *crtc)
0163 {
0164 #ifdef CONFIG_DEBUG_FS
0165 kfree(crtc->crc.source);
0166 #endif
0167 }
0168
0169 static const struct dma_fence_ops drm_crtc_fence_ops;
0170
0171 static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
0172 {
0173 BUG_ON(fence->ops != &drm_crtc_fence_ops);
0174 return container_of(fence->lock, struct drm_crtc, fence_lock);
0175 }
0176
0177 static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
0178 {
0179 struct drm_crtc *crtc = fence_to_crtc(fence);
0180
0181 return crtc->dev->driver->name;
0182 }
0183
0184 static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)
0185 {
0186 struct drm_crtc *crtc = fence_to_crtc(fence);
0187
0188 return crtc->timeline_name;
0189 }
0190
0191 static const struct dma_fence_ops drm_crtc_fence_ops = {
0192 .get_driver_name = drm_crtc_fence_get_driver_name,
0193 .get_timeline_name = drm_crtc_fence_get_timeline_name,
0194 };
0195
0196 struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
0197 {
0198 struct dma_fence *fence;
0199
0200 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
0201 if (!fence)
0202 return NULL;
0203
0204 dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
0205 crtc->fence_context, ++crtc->fence_seqno);
0206
0207 return fence;
0208 }
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 __printf(6, 0)
0247 static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
0248 struct drm_plane *primary,
0249 struct drm_plane *cursor,
0250 const struct drm_crtc_funcs *funcs,
0251 const char *name, va_list ap)
0252 {
0253 struct drm_mode_config *config = &dev->mode_config;
0254 int ret;
0255
0256 WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
0257 WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
0258
0259
0260 if (WARN_ON(config->num_crtc >= 32))
0261 return -EINVAL;
0262
0263 WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
0264 (!funcs->atomic_destroy_state ||
0265 !funcs->atomic_duplicate_state));
0266
0267 crtc->dev = dev;
0268 crtc->funcs = funcs;
0269
0270 INIT_LIST_HEAD(&crtc->commit_list);
0271 spin_lock_init(&crtc->commit_lock);
0272
0273 drm_modeset_lock_init(&crtc->mutex);
0274 ret = drm_mode_object_add(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
0275 if (ret)
0276 return ret;
0277
0278 if (name) {
0279 crtc->name = kvasprintf(GFP_KERNEL, name, ap);
0280 } else {
0281 crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
0282 drm_num_crtcs(dev));
0283 }
0284 if (!crtc->name) {
0285 drm_mode_object_unregister(dev, &crtc->base);
0286 return -ENOMEM;
0287 }
0288
0289 crtc->fence_context = dma_fence_context_alloc(1);
0290 spin_lock_init(&crtc->fence_lock);
0291 snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),
0292 "CRTC:%d-%s", crtc->base.id, crtc->name);
0293
0294 crtc->base.properties = &crtc->properties;
0295
0296 list_add_tail(&crtc->head, &config->crtc_list);
0297 crtc->index = config->num_crtc++;
0298
0299 crtc->primary = primary;
0300 crtc->cursor = cursor;
0301 if (primary && !primary->possible_crtcs)
0302 primary->possible_crtcs = drm_crtc_mask(crtc);
0303 if (cursor && !cursor->possible_crtcs)
0304 cursor->possible_crtcs = drm_crtc_mask(crtc);
0305
0306 ret = drm_crtc_crc_init(crtc);
0307 if (ret) {
0308 drm_mode_object_unregister(dev, &crtc->base);
0309 return ret;
0310 }
0311
0312 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
0313 drm_object_attach_property(&crtc->base, config->prop_active, 0);
0314 drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
0315 drm_object_attach_property(&crtc->base,
0316 config->prop_out_fence_ptr, 0);
0317 drm_object_attach_property(&crtc->base,
0318 config->prop_vrr_enabled, 0);
0319 }
0320
0321 return 0;
0322 }
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353 int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
0354 struct drm_plane *primary,
0355 struct drm_plane *cursor,
0356 const struct drm_crtc_funcs *funcs,
0357 const char *name, ...)
0358 {
0359 va_list ap;
0360 int ret;
0361
0362 WARN_ON(!funcs->destroy);
0363
0364 va_start(ap, name);
0365 ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
0366 name, ap);
0367 va_end(ap);
0368
0369 return ret;
0370 }
0371 EXPORT_SYMBOL(drm_crtc_init_with_planes);
0372
0373 static void drmm_crtc_alloc_with_planes_cleanup(struct drm_device *dev,
0374 void *ptr)
0375 {
0376 struct drm_crtc *crtc = ptr;
0377
0378 drm_crtc_cleanup(crtc);
0379 }
0380
0381 void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
0382 size_t size, size_t offset,
0383 struct drm_plane *primary,
0384 struct drm_plane *cursor,
0385 const struct drm_crtc_funcs *funcs,
0386 const char *name, ...)
0387 {
0388 void *container;
0389 struct drm_crtc *crtc;
0390 va_list ap;
0391 int ret;
0392
0393 if (WARN_ON(!funcs || funcs->destroy))
0394 return ERR_PTR(-EINVAL);
0395
0396 container = drmm_kzalloc(dev, size, GFP_KERNEL);
0397 if (!container)
0398 return ERR_PTR(-ENOMEM);
0399
0400 crtc = container + offset;
0401
0402 va_start(ap, name);
0403 ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
0404 name, ap);
0405 va_end(ap);
0406 if (ret)
0407 return ERR_PTR(ret);
0408
0409 ret = drmm_add_action_or_reset(dev, drmm_crtc_alloc_with_planes_cleanup,
0410 crtc);
0411 if (ret)
0412 return ERR_PTR(ret);
0413
0414 return container;
0415 }
0416 EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426 void drm_crtc_cleanup(struct drm_crtc *crtc)
0427 {
0428 struct drm_device *dev = crtc->dev;
0429
0430
0431
0432
0433
0434
0435 drm_crtc_crc_fini(crtc);
0436
0437 kfree(crtc->gamma_store);
0438 crtc->gamma_store = NULL;
0439
0440 drm_modeset_lock_fini(&crtc->mutex);
0441
0442 drm_mode_object_unregister(dev, &crtc->base);
0443 list_del(&crtc->head);
0444 dev->mode_config.num_crtc--;
0445
0446 WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
0447 if (crtc->state && crtc->funcs->atomic_destroy_state)
0448 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
0449
0450 kfree(crtc->name);
0451
0452 memset(crtc, 0, sizeof(*crtc));
0453 }
0454 EXPORT_SYMBOL(drm_crtc_cleanup);
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469 int drm_mode_getcrtc(struct drm_device *dev,
0470 void *data, struct drm_file *file_priv)
0471 {
0472 struct drm_mode_crtc *crtc_resp = data;
0473 struct drm_crtc *crtc;
0474 struct drm_plane *plane;
0475
0476 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0477 return -EOPNOTSUPP;
0478
0479 crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id);
0480 if (!crtc)
0481 return -ENOENT;
0482
0483 plane = crtc->primary;
0484
0485 crtc_resp->gamma_size = crtc->gamma_size;
0486
0487 drm_modeset_lock(&plane->mutex, NULL);
0488 if (plane->state && plane->state->fb)
0489 crtc_resp->fb_id = plane->state->fb->base.id;
0490 else if (!plane->state && plane->fb)
0491 crtc_resp->fb_id = plane->fb->base.id;
0492 else
0493 crtc_resp->fb_id = 0;
0494
0495 if (plane->state) {
0496 crtc_resp->x = plane->state->src_x >> 16;
0497 crtc_resp->y = plane->state->src_y >> 16;
0498 }
0499 drm_modeset_unlock(&plane->mutex);
0500
0501 drm_modeset_lock(&crtc->mutex, NULL);
0502 if (crtc->state) {
0503 if (crtc->state->enable) {
0504 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
0505 crtc_resp->mode_valid = 1;
0506 } else {
0507 crtc_resp->mode_valid = 0;
0508 }
0509 } else {
0510 crtc_resp->x = crtc->x;
0511 crtc_resp->y = crtc->y;
0512
0513 if (crtc->enabled) {
0514 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
0515 crtc_resp->mode_valid = 1;
0516
0517 } else {
0518 crtc_resp->mode_valid = 0;
0519 }
0520 }
0521 if (!file_priv->aspect_ratio_allowed)
0522 crtc_resp->mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
0523 drm_modeset_unlock(&crtc->mutex);
0524
0525 return 0;
0526 }
0527
0528 static int __drm_mode_set_config_internal(struct drm_mode_set *set,
0529 struct drm_modeset_acquire_ctx *ctx)
0530 {
0531 struct drm_crtc *crtc = set->crtc;
0532 struct drm_framebuffer *fb;
0533 struct drm_crtc *tmp;
0534 int ret;
0535
0536 WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
0537
0538
0539
0540
0541
0542
0543 drm_for_each_crtc(tmp, crtc->dev) {
0544 struct drm_plane *plane = tmp->primary;
0545
0546 plane->old_fb = plane->fb;
0547 }
0548
0549 fb = set->fb;
0550
0551 ret = crtc->funcs->set_config(set, ctx);
0552 if (ret == 0) {
0553 struct drm_plane *plane = crtc->primary;
0554
0555 plane->crtc = fb ? crtc : NULL;
0556 plane->fb = fb;
0557 }
0558
0559 drm_for_each_crtc(tmp, crtc->dev) {
0560 struct drm_plane *plane = tmp->primary;
0561
0562 if (plane->fb)
0563 drm_framebuffer_get(plane->fb);
0564 if (plane->old_fb)
0565 drm_framebuffer_put(plane->old_fb);
0566 plane->old_fb = NULL;
0567 }
0568
0569 return ret;
0570 }
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585 int drm_mode_set_config_internal(struct drm_mode_set *set)
0586 {
0587 WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev));
0588
0589 return __drm_mode_set_config_internal(set, NULL);
0590 }
0591 EXPORT_SYMBOL(drm_mode_set_config_internal);
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602 int drm_crtc_check_viewport(const struct drm_crtc *crtc,
0603 int x, int y,
0604 const struct drm_display_mode *mode,
0605 const struct drm_framebuffer *fb)
0606
0607 {
0608 int hdisplay, vdisplay;
0609
0610 drm_mode_get_hv_timing(mode, &hdisplay, &vdisplay);
0611
0612 if (crtc->state &&
0613 drm_rotation_90_or_270(crtc->primary->state->rotation))
0614 swap(hdisplay, vdisplay);
0615
0616 return drm_framebuffer_check_src_coords(x << 16, y << 16,
0617 hdisplay << 16, vdisplay << 16,
0618 fb);
0619 }
0620 EXPORT_SYMBOL(drm_crtc_check_viewport);
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635 int drm_mode_setcrtc(struct drm_device *dev, void *data,
0636 struct drm_file *file_priv)
0637 {
0638 struct drm_mode_config *config = &dev->mode_config;
0639 struct drm_mode_crtc *crtc_req = data;
0640 struct drm_crtc *crtc;
0641 struct drm_plane *plane;
0642 struct drm_connector **connector_set = NULL, *connector;
0643 struct drm_framebuffer *fb = NULL;
0644 struct drm_display_mode *mode = NULL;
0645 struct drm_mode_set set;
0646 uint32_t __user *set_connectors_ptr;
0647 struct drm_modeset_acquire_ctx ctx;
0648 int ret;
0649 int i;
0650
0651 if (!drm_core_check_feature(dev, DRIVER_MODESET))
0652 return -EOPNOTSUPP;
0653
0654
0655
0656
0657
0658 if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
0659 return -ERANGE;
0660
0661 crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);
0662 if (!crtc) {
0663 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
0664 return -ENOENT;
0665 }
0666 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
0667
0668 plane = crtc->primary;
0669
0670
0671 if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id))
0672 return -EACCES;
0673
0674 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx,
0675 DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
0676
0677 if (crtc_req->mode_valid) {
0678
0679
0680 if (crtc_req->fb_id == -1) {
0681 struct drm_framebuffer *old_fb;
0682
0683 if (plane->state)
0684 old_fb = plane->state->fb;
0685 else
0686 old_fb = plane->fb;
0687
0688 if (!old_fb) {
0689 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
0690 ret = -EINVAL;
0691 goto out;
0692 }
0693
0694 fb = old_fb;
0695
0696 drm_framebuffer_get(fb);
0697 } else {
0698 fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);
0699 if (!fb) {
0700 DRM_DEBUG_KMS("Unknown FB ID%d\n",
0701 crtc_req->fb_id);
0702 ret = -ENOENT;
0703 goto out;
0704 }
0705 }
0706
0707 mode = drm_mode_create(dev);
0708 if (!mode) {
0709 ret = -ENOMEM;
0710 goto out;
0711 }
0712 if (!file_priv->aspect_ratio_allowed &&
0713 (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != DRM_MODE_FLAG_PIC_AR_NONE) {
0714 DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n");
0715 ret = -EINVAL;
0716 goto out;
0717 }
0718
0719
0720 ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
0721 if (ret) {
0722 DRM_DEBUG_KMS("Invalid mode (ret=%d, status=%s)\n",
0723 ret, drm_get_mode_status_name(mode->status));
0724 drm_mode_debug_printmodeline(mode);
0725 goto out;
0726 }
0727
0728
0729
0730
0731
0732
0733
0734
0735 if (!plane->format_default) {
0736 ret = drm_plane_check_pixel_format(plane,
0737 fb->format->format,
0738 fb->modifier);
0739 if (ret) {
0740 DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n",
0741 &fb->format->format,
0742 fb->modifier);
0743 goto out;
0744 }
0745 }
0746
0747 ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
0748 mode, fb);
0749 if (ret)
0750 goto out;
0751
0752 }
0753
0754 if (crtc_req->count_connectors == 0 && mode) {
0755 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
0756 ret = -EINVAL;
0757 goto out;
0758 }
0759
0760 if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
0761 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
0762 crtc_req->count_connectors);
0763 ret = -EINVAL;
0764 goto out;
0765 }
0766
0767 if (crtc_req->count_connectors > 0) {
0768 u32 out_id;
0769
0770
0771 if (crtc_req->count_connectors > config->num_connector) {
0772 ret = -EINVAL;
0773 goto out;
0774 }
0775
0776 connector_set = kmalloc_array(crtc_req->count_connectors,
0777 sizeof(struct drm_connector *),
0778 GFP_KERNEL);
0779 if (!connector_set) {
0780 ret = -ENOMEM;
0781 goto out;
0782 }
0783
0784 for (i = 0; i < crtc_req->count_connectors; i++) {
0785 connector_set[i] = NULL;
0786 set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
0787 if (get_user(out_id, &set_connectors_ptr[i])) {
0788 ret = -EFAULT;
0789 goto out;
0790 }
0791
0792 connector = drm_connector_lookup(dev, file_priv, out_id);
0793 if (!connector) {
0794 DRM_DEBUG_KMS("Connector id %d unknown\n",
0795 out_id);
0796 ret = -ENOENT;
0797 goto out;
0798 }
0799 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
0800 connector->base.id,
0801 connector->name);
0802
0803 connector_set[i] = connector;
0804 }
0805 }
0806
0807 set.crtc = crtc;
0808 set.x = crtc_req->x;
0809 set.y = crtc_req->y;
0810 set.mode = mode;
0811 set.connectors = connector_set;
0812 set.num_connectors = crtc_req->count_connectors;
0813 set.fb = fb;
0814
0815 if (drm_drv_uses_atomic_modeset(dev))
0816 ret = crtc->funcs->set_config(&set, &ctx);
0817 else
0818 ret = __drm_mode_set_config_internal(&set, &ctx);
0819
0820 out:
0821 if (fb)
0822 drm_framebuffer_put(fb);
0823
0824 if (connector_set) {
0825 for (i = 0; i < crtc_req->count_connectors; i++) {
0826 if (connector_set[i])
0827 drm_connector_put(connector_set[i]);
0828 }
0829 }
0830 kfree(connector_set);
0831 drm_mode_destroy(dev, mode);
0832
0833
0834 connector_set = NULL;
0835 fb = NULL;
0836 mode = NULL;
0837
0838 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
0839
0840 return ret;
0841 }
0842
0843 int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
0844 struct drm_property *property,
0845 uint64_t value)
0846 {
0847 int ret = -EINVAL;
0848 struct drm_crtc *crtc = obj_to_crtc(obj);
0849
0850 if (crtc->funcs->set_property)
0851 ret = crtc->funcs->set_property(crtc, property, value);
0852 if (!ret)
0853 drm_object_property_set_value(obj, property, value);
0854
0855 return ret;
0856 }
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872 int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
0873 unsigned int supported_filters)
0874 {
0875 struct drm_property *prop =
0876 drm_create_scaling_filter_prop(crtc->dev, supported_filters);
0877
0878 if (IS_ERR(prop))
0879 return PTR_ERR(prop);
0880
0881 drm_object_attach_property(&crtc->base, prop,
0882 DRM_SCALING_FILTER_DEFAULT);
0883 crtc->scaling_filter_property = prop;
0884
0885 return 0;
0886 }
0887 EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);