diff options
| -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); | 
