diff options
author | Dave Airlie <airlied@redhat.com> | 2008-06-02 16:45:44 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2008-06-02 16:45:44 +1000 |
commit | 149b17311ad5f117e8f53a7a8cc032e369b95ed2 (patch) | |
tree | f3e42a300471992c34d308de63243932f4101190 /linux-core | |
parent | 50d3e5bd020d0b6877a5fef441408f16e31121cd (diff) |
drm: initial mode object groups.
This creates a default group attached to the legacy drm minor nodes.
It covers all the objects in the set. make set resources only return
objects for this set. Need to fix up other functions to only work on
objects in their allowed set.
Diffstat (limited to 'linux-core')
-rw-r--r-- | linux-core/drmP.h | 2 | ||||
-rw-r--r-- | linux-core/drm_crtc.c | 154 | ||||
-rw-r--r-- | linux-core/drm_crtc.h | 11 | ||||
-rw-r--r-- | linux-core/drm_stub.c | 5 |
4 files changed, 135 insertions, 37 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 7c7e201a..11c01386 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -792,7 +792,7 @@ struct drm_minor { struct drm_master *master; /* currently active master for this node */ struct list_head master_list; - /* possibly needs a list of configured modesetting pieces */ + struct drm_mode_group mode_group; }; 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); diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 3c11dfc6..01cf9af7 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -519,6 +519,15 @@ struct drm_mode_config_funcs { bool (*resize_fb)(struct drm_device *dev, struct drm_framebuffer *fb); }; +struct drm_mode_group { + uint32_t num_crtcs; + uint32_t num_encoders; + uint32_t num_connectors; + + /* list of object IDs for this group */ + uint32_t *id_list; +}; + /** * drm_mode_config - Mode configuration control structure * @@ -591,7 +600,7 @@ extern void drm_encoder_cleanup(struct drm_encoder *encoder); extern char *drm_get_connector_name(struct drm_connector *connector); extern char *drm_get_dpms_name(int val); extern void drm_fb_release(struct file *filp); - +extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); extern struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter); extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index f66dec07..45b8f386 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -378,6 +378,11 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, if ((ret = dev->driver->load(dev, ent->driver_data))) goto err_g5; + /* setup the grouping for the legacy output */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + if (drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group)) + goto err_g5; + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary->index); |