summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_crtc.c154
-rw-r--r--linux-core/drm_crtc.h11
-rw-r--r--linux-core/drm_stub.c5
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);