diff options
Diffstat (limited to 'linux-core/drm_crtc.c')
-rw-r--r-- | linux-core/drm_crtc.c | 154 |
1 files changed, 119 insertions, 35 deletions
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 79dc137e..784c2f74 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -585,6 +585,45 @@ void drm_mode_config_init(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_config_init); +int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) +{ + uint32_t total_objects = 0; + + total_objects += dev->mode_config.num_crtc; + total_objects += dev->mode_config.num_connector; + total_objects += dev->mode_config.num_encoder; + + group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); + if (!group->id_list) + return -ENOMEM; + + group->num_crtcs = 0; + group->num_connectors = 0; + group->num_encoders = 0; + return 0; +} + +int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group) +{ + struct drm_crtc *crtc; + struct drm_encoder *encoder; + struct drm_connector *connector; + + if (drm_mode_group_init(dev, group)) + return -ENOMEM; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + group->id_list[group->num_crtcs++] = crtc->base.id; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) + group->id_list[group->num_crtcs + group->num_encoders++] = encoder->base.id; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + group->id_list[group->num_crtcs + group->num_encoders + group->num_connectors++] = connector->base.id; + + return 0; +} + /** * drm_get_buffer_object - find the buffer object for a given handle * @dev: DRM device @@ -786,25 +825,37 @@ int drm_mode_getresources(struct drm_device *dev, int crtc_count = 0; int fb_count = 0; int encoder_count = 0; - int copied = 0; + int copied = 0, i; uint32_t __user *fb_id; uint32_t __user *crtc_id; uint32_t __user *connector_id; uint32_t __user *encoder_id; + struct drm_mode_group *mode_group; mutex_lock(&dev->mode_config.mutex); + /* for the non-control nodes we need to limit the list of resources by IDs in the + group list for this node */ list_for_each(lh, &file_priv->fbs) fb_count++; - list_for_each(lh, &dev->mode_config.crtc_list) - crtc_count++; + mode_group = &file_priv->master->minor->mode_group; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + + list_for_each(lh, &dev->mode_config.crtc_list) + crtc_count++; - list_for_each(lh, &dev->mode_config.connector_list) - connector_count++; + list_for_each(lh, &dev->mode_config.connector_list) + connector_count++; - list_for_each(lh, &dev->mode_config.encoder_list) - encoder_count++; + list_for_each(lh, &dev->mode_config.encoder_list) + encoder_count++; + } else { + + crtc_count = mode_group->num_crtcs; + connector_count = mode_group->num_connectors; + encoder_count = mode_group->num_encoders; + } card_res->max_height = dev->mode_config.max_height; card_res->min_height = dev->mode_config.min_height; @@ -830,49 +881,82 @@ int drm_mode_getresources(struct drm_device *dev, if (card_res->count_crtcs >= crtc_count) { copied = 0; crtc_id = (uint32_t *)(unsigned long)card_res->crtc_id_ptr; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){ - DRM_DEBUG("CRTC ID is %d\n", crtc->base.id); - if (put_user(crtc->base.id, crtc_id + copied)) { - ret = -EFAULT; - goto out; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + DRM_DEBUG("CRTC ID is %d\n", crtc->base.id); + if (put_user(crtc->base.id, crtc_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + for (i = 0; i < mode_group->num_crtcs; i++) { + if (put_user(mode_group->id_list[i], crtc_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; } - copied++; } } card_res->count_crtcs = crtc_count; + /* Encoders */ + if (card_res->count_encoders >= encoder_count) { + copied = 0; + encoder_id = (uint32_t *)(unsigned long)card_res->encoder_id_ptr; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(encoder, &dev->mode_config.encoder_list, + head) { + DRM_DEBUG("ENCODER ID is %d\n", encoder->base.id); + if (put_user(encoder->base.id, encoder_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) { + if (put_user(mode_group->id_list[i], encoder_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + + } + } + card_res->count_encoders = encoder_count; /* Connectors */ if (card_res->count_connectors >= connector_count) { copied = 0; connector_id = (uint32_t *)(unsigned long)card_res->connector_id_ptr; - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { - DRM_DEBUG("CONNECTOR ID is %d\n", connector->base.id); - if (put_user(connector->base.id, connector_id + copied)) { - ret = -EFAULT; - goto out; + if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { + list_for_each_entry(connector, &dev->mode_config.connector_list, + head) { + DRM_DEBUG("CONNECTOR ID is %d\n", connector->base.id); + if (put_user(connector->base.id, connector_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; + } + } else { + int start = mode_group->num_crtcs + mode_group->num_encoders; + for (i = start; i < start + mode_group->num_connectors; i++) { + if (put_user(mode_group->id_list[i], connector_id + copied)) { + ret = -EFAULT; + goto out; + } + copied++; } - copied++; } } card_res->count_connectors = connector_count; + - /* Encoders */ - if (card_res->count_encoders >= encoder_count) { - copied = 0; - encoder_id = (uint32_t *)(unsigned long)card_res->encoder_id_ptr; - list_for_each_entry(encoder, &dev->mode_config.encoder_list, - head) { - DRM_DEBUG("ENCODER ID is %d\n", encoder->base.id); - if (put_user(encoder->base.id, encoder_id + copied)) { - ret = -EFAULT; - goto out; - } - copied++; - } - } - card_res->count_encoders = encoder_count; DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, card_res->count_connectors, card_res->count_encoders); |