summaryrefslogtreecommitdiff
path: root/linux-core/drm_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core/drm_crtc.c')
-rw-r--r--linux-core/drm_crtc.c154
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);