• Linux内核4.14版本——drm框架分析(12)——DRM_IOCTL_MODE_SETCRTC(drm_mode_setcrtc)


    目录

    1. drm_mode_setcrtc

    1.1 根据应用传入的crtc_id找到crtc

    1.2 根据应用传入的fb_id,找到对应的drm_framebuffer

    1.3  根据应用传入的mode,创建一个drm_display_mode

    1.4 根据传入的set_connectors_ptr,找到驱动对应的connector

    1.5 将以上信息转为struct drm_mode_set并调用__drm_mode_set_config_internal

    1.6 __drm_mode_set_config_internal

    2. drm_atomic_helper_set_config

    3. 流程图


            本文分析一下drm_mode_setcrtc。

    1. drm_mode_setcrtc

    1.1 根据应用传入的crtc_id找到crtc

    1. int drm_mode_setcrtc(struct drm_device *dev, void *data,
    2. struct drm_file *file_priv)
    3. {
    4. ......
    5. crtc = drm_crtc_find(dev, crtc_req->crtc_id);
    6. if (!crtc) {
    7. DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
    8. return -ENOENT;
    9. }
    10. DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);

    1.2 根据应用传入的fb_id,找到对应的drm_framebuffer

    1. if (crtc_req->mode_valid) {
    2. /* If we have a mode we need a framebuffer. */
    3. /* If we pass -1, set the mode with the currently bound fb */
    4. if (crtc_req->fb_id == -1) {
    5. if (!crtc->primary->fb) {
    6. DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
    7. ret = -EINVAL;
    8. goto out;
    9. }
    10. fb = crtc->primary->fb;
    11. /* Make refcounting symmetric with the lookup path. */
    12. drm_framebuffer_get(fb);
    13. } else {
    14. fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
    15. if (!fb) {
    16. DRM_DEBUG_KMS("Unknown FB ID%d\n",
    17. crtc_req->fb_id);
    18. ret = -ENOENT;
    19. goto out;
    20. }

    1.3  根据应用传入的mode,创建一个drm_display_mode

    1. mode = drm_mode_create(dev);
    2. if (!mode) {
    3. ret = -ENOMEM;
    4. goto out;
    5. }
    6. ret = drm_mode_convert_umode(mode, &crtc_req->mode);
    7. if (ret) {
    8. DRM_DEBUG_KMS("Invalid mode\n");
    9. goto out;
    10. }
    11. /*
    12. * Check whether the primary plane supports the fb pixel format.
    13. * Drivers not implementing the universal planes API use a
    14. * default formats list provided by the DRM core which doesn't
    15. * match real hardware capabilities. Skip the check in that
    16. * case.
    17. */
    18. if (!crtc->primary->format_default) {
    19. ret = drm_plane_check_pixel_format(crtc->primary,
    20. fb->format->format);
    21. if (ret) {
    22. struct drm_format_name_buf format_name;
    23. DRM_DEBUG_KMS("Invalid pixel format %s\n",
    24. drm_get_format_name(fb->format->format,
    25. &format_name));
    26. goto out;
    27. }
    28. }
    29. ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
    30. mode, fb);
    31. if (ret)
    32. goto out;

    1.4 根据传入的set_connectors_ptr,找到驱动对应的connector

    1. for (i = 0; i < crtc_req->count_connectors; i++) {
    2. connector_set[i] = NULL;
    3. set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
    4. if (get_user(out_id, &set_connectors_ptr[i])) {
    5. ret = -EFAULT;
    6. goto out;
    7. }
    8. connector = drm_connector_lookup(dev, out_id);
    9. if (!connector) {
    10. DRM_DEBUG_KMS("Connector id %d unknown\n",
    11. out_id);
    12. ret = -ENOENT;
    13. goto out;
    14. }
    15. DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
    16. connector->base.id,
    17. connector->name);
    18. connector_set[i] = connector;
    19. }

    1.5 将以上信息转为struct drm_mode_set并调用__drm_mode_set_config_internal

    1. set.crtc = crtc;
    2. set.x = crtc_req->x;
    3. set.y = crtc_req->y;
    4. set.mode = mode;
    5. set.connectors = connector_set;
    6. set.num_connectors = crtc_req->count_connectors;
    7. set.fb = fb;
    8. ret = __drm_mode_set_config_internal(&set, &ctx);

    1.6 __drm_mode_set_config_internal

    1. static int __drm_mode_set_config_internal(struct drm_mode_set *set,
    2. struct drm_modeset_acquire_ctx *ctx)
    3. {
    4. struct drm_crtc *crtc = set->crtc;
    5. struct drm_framebuffer *fb;
    6. struct drm_crtc *tmp;
    7. int ret;
    8. /*
    9. * NOTE: ->set_config can also disable other crtcs (if we steal all
    10. * connectors from it), hence we need to refcount the fbs across all
    11. * crtcs. Atomic modeset will have saner semantics ...
    12. */
    13. drm_for_each_crtc(tmp, crtc->dev)
    14. tmp->primary->old_fb = tmp->primary->fb;
    15. fb = set->fb;
    16. ret = crtc->funcs->set_config(set, ctx);
    17. if (ret == 0) {
    18. crtc->primary->crtc = crtc;
    19. crtc->primary->fb = fb;
    20. }
    21. drm_for_each_crtc(tmp, crtc->dev) {
    22. if (tmp->primary->fb)
    23. drm_framebuffer_get(tmp->primary->fb);
    24. if (tmp->primary->old_fb)
    25. drm_framebuffer_put(tmp->primary->old_fb);
    26. tmp->primary->old_fb = NULL;
    27. }
    28. return ret;
    29. }

            只要是调用ret = crtc->funcs->set_config(set, ctx),即drm_atomic_helper_set_config,

    1. static const struct drm_crtc_funcs malidp_crtc_funcs = {
    2. .gamma_set = drm_atomic_helper_legacy_gamma_set,
    3. .destroy = drm_crtc_cleanup,
    4. .set_config = drm_atomic_helper_set_config,
    5. .page_flip = drm_atomic_helper_page_flip,
    6. .reset = malidp_crtc_reset,
    7. .atomic_duplicate_state = malidp_crtc_duplicate_state,
    8. .atomic_destroy_state = malidp_crtc_destroy_state,
    9. .enable_vblank = malidp_crtc_enable_vblank,
    10. .disable_vblank = malidp_crtc_disable_vblank,
    11. };

    2. drm_atomic_helper_set_config

    1. int drm_atomic_helper_set_config(struct drm_mode_set *set,
    2. struct drm_modeset_acquire_ctx *ctx)
    3. {
    4. struct drm_atomic_state *state;
    5. struct drm_crtc *crtc = set->crtc;
    6. int ret = 0;
    7. state = drm_atomic_state_alloc(crtc->dev);
    8. if (!state)
    9. return -ENOMEM;
    10. state->acquire_ctx = ctx;
    11. ret = __drm_atomic_helper_set_config(set, state);
    12. if (ret != 0)
    13. goto fail;
    14. ret = handle_conflicting_encoders(state, true);
    15. if (ret)
    16. goto fail;
    17. ret = drm_atomic_commit(state);
    18. fail:
    19. drm_atomic_state_put(state);
    20. return ret;
    21. }

            drm_atomic_helper_set_config主要涉及到结构体struct drm_atomic_state和drm_atomic_commit函数,我们后面会单独讨论这2个。

    3. 流程图

  • 相关阅读:
    GnuTLS recv error (-54): Error in the pull function.
    qt tcp 连接 秒断连
    端子排中间继电器WZY-400W
    【笔记篇】10仓管系统库内管理——之《实战供应链》
    P2105 K皇后
    【深度学习】SimSwap: An Efficient Framework For High Fidelity Face Swapping 换脸,实战
    HTML5网页设计制作基础大二dreamweaver作业、使用HTML+CSS技术制作博客网站(5个页面)
    springcloud组件
    Verilog刷题笔记37
    【✨十五天搞定电工基础】一阶电路的暂态分析
  • 原文地址:https://blog.csdn.net/yangguoyu8023/article/details/129258226