diff mbox

[2/6] drm: add tile_group support. (v2)

Message ID 1413945127-31793-3-git-send-email-airlied@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Dave Airlie Oct. 22, 2014, 2:32 a.m. UTC
From: Dave Airlie <airlied@redhat.com>

A tile group is an identifier shared by a single monitor,
DisplayID topology has 8 bytes we can use for this, just
use those for now until something else comes up in the
future. We assign these to an idr and use the idr to
tell userspace what connectors are in the same tile group.

DisplayID v1.3 says the serial number must be unique for
displays from the same manufacturer.

v2:
destroy idr (dvdhrm)
add docbook (danvet)
airlied:- not sure how to make docbook add fns to tile group section.

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 Documentation/DocBook/drm.tmpl |  4 ++
 drivers/gpu/drm/drm_crtc.c     | 99 ++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h         | 16 +++++++
 3 files changed, 119 insertions(+)

Comments

Daniel Vetter Oct. 22, 2014, 8:15 a.m. UTC | #1
On Wed, Oct 22, 2014 at 12:32:03PM +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied@redhat.com>
> 
> A tile group is an identifier shared by a single monitor,
> DisplayID topology has 8 bytes we can use for this, just
> use those for now until something else comes up in the
> future. We assign these to an idr and use the idr to
> tell userspace what connectors are in the same tile group.
> 
> DisplayID v1.3 says the serial number must be unique for
> displays from the same manufacturer.
> 
> v2:
> destroy idr (dvdhrm)
> add docbook (danvet)
> airlied:- not sure how to make docbook add fns to tile group section.

Either you have to extract them into a new file or you have to list them
all explicitly. The kerneldoc nano howto has the various options you can
use. Thus far we haven't documented drm-internal functions though, only
those exported to drivers or helpers as guidelines to driver writers. Not
stopping you ofc ;-) But imo just documenting the tile prop registration
function is good enough.

wrt the patch I'm not 100% sure the kref_get_unless_zero is perfectly
race-free, but that depends upon how we solve the hotplugging of
properties and stuff I think.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
>  Documentation/DocBook/drm.tmpl |  4 ++
>  drivers/gpu/drm/drm_crtc.c     | 99 ++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_crtc.h         | 16 +++++++
>  3 files changed, 119 insertions(+)
> 
> diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
> index 0a5cbbb..5ea6289 100644
> --- a/Documentation/DocBook/drm.tmpl
> +++ b/Documentation/DocBook/drm.tmpl
> @@ -2374,6 +2374,10 @@ void intel_crt_init(struct drm_device *dev)
>        <title id="drm-kms-planehelpers">Plane Helper Reference</title>
>  !Edrivers/gpu/drm/drm_plane_helper.c Plane Helpers
>      </sect2>
> +    <sect2>
> +	  <title>Tile group</title>
> +!Pdrivers/gpu/drm/drm_crtc.c Tile group
> +    </sect2>
>    </sect1>
>  
>    <!-- Internals: kms properties -->
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 363301c..7f45fdc 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -5047,6 +5047,7 @@ void drm_mode_config_init(struct drm_device *dev)
>  	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
>  	INIT_LIST_HEAD(&dev->mode_config.plane_list);
>  	idr_init(&dev->mode_config.crtc_idr);
> +	idr_init(&dev->mode_config.tile_idr);
>  
>  	drm_modeset_lock_all(dev);
>  	drm_mode_create_standard_connector_properties(dev);
> @@ -5134,6 +5135,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
>  		crtc->funcs->destroy(crtc);
>  	}
>  
> +	idr_destroy(&dev->mode_config.tile_idr);
>  	idr_destroy(&dev->mode_config.crtc_idr);
>  	drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
>  }
> @@ -5156,3 +5158,100 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
>  					   supported_rotations);
>  }
>  EXPORT_SYMBOL(drm_mode_create_rotation_property);
> +
> +/**
> + * DOC: Tile group
> + *
> + * Tile groups are used to represent tiled monitors with a unique
> + * integer identifier. Tiled monitors using DisplayID v1.3 have
> + * a unique 8-byte handle, we store this in a tile group, so we
> + * have a common identifier for all tiles in a monitor group.
> + */
> +static void drm_tile_group_free(struct kref *kref)
> +{
> +	struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
> +	struct drm_device *dev = tg->dev;
> +	mutex_lock(&dev->mode_config.idr_mutex);
> +	idr_remove(&dev->mode_config.tile_idr, tg->id);
> +	mutex_lock(&dev->mode_config.idr_mutex);
> +	kfree(tg);
> +}
> +
> +/**
> + * drm_mode_put_tile_group - drop a reference to a tile group.
> + * @dev: DRM device
> + * @tg: tile group to drop reference to.
> + *
> + * drop reference to tile group and free if 0.
> + */
> +void drm_mode_put_tile_group(struct drm_device *dev,
> +			     struct drm_tile_group *tg)
> +{
> +	kref_put(&tg->refcount, drm_tile_group_free);
> +}
> +
> +/**
> + * drm_mode_get_tile_group - get a reference to an existing tile group
> + * @dev: DRM device
> + * @topology: 8-bytes unique per monitor.
> + *
> + * Use the unique bytes to get a reference to an existing tile group.
> + *
> + * RETURNS:
> + * tile group or NULL if not found.
> + */
> +struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
> +					       char topology[8])
> +{
> +	struct drm_tile_group *tg;
> +	int id;
> +	mutex_lock(&dev->mode_config.idr_mutex);
> +	idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
> +		if (!memcmp(tg->group_data, topology, 8)) {
> +			if (!kref_get_unless_zero(&tg->refcount))
> +				tg = NULL;
> +			mutex_unlock(&dev->mode_config.idr_mutex);
> +			return tg;
> +		}
> +	}
> +	mutex_unlock(&dev->mode_config.idr_mutex);
> +	return NULL;
> +}
> +
> +/**
> + * drm_mode_create_tile_group - create a tile group from a displayid description
> + * @dev: DRM device
> + * @topology: 8-bytes unique per monitor.
> + *
> + * Create a tile group for the unique monitor, and get a unique
> + * identifier for the tile group.
> + *
> + * RETURNS:
> + * new tile group or error.
> + */
> +struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
> +						  char topology[8])
> +{
> +	struct drm_tile_group *tg;
> +	int ret;
> +
> +	tg = kzalloc(sizeof(*tg), GFP_KERNEL);
> +	if (!tg)
> +		return ERR_PTR(-ENOMEM);
> +
> +	kref_init(&tg->refcount);
> +	memcpy(tg->group_data, topology, 8);
> +	tg->dev = dev;
> +
> +	mutex_lock(&dev->mode_config.idr_mutex);
> +	ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
> +	if (ret >= 0) {
> +		tg->id = ret;
> +	} else {
> +		kfree(tg);
> +		tg = ERR_PTR(ret);
> +	}
> +
> +	mutex_unlock(&dev->mode_config.idr_mutex);
> +	return tg;
> +}
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index f1105d0..afaec4b 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -136,6 +136,14 @@ struct drm_display_info {
>  	u8 cea_rev;
>  };
>  
> +/* data corresponds to displayid vend/prod/serial */
> +struct drm_tile_group {
> +	struct kref refcount;
> +	struct drm_device *dev;
> +	int id;
> +	u8 group_data[8];
> +};
> +
>  struct drm_framebuffer_funcs {
>  	/* note: use drm_framebuffer_remove() */
>  	void (*destroy)(struct drm_framebuffer *framebuffer);
> @@ -770,6 +778,7 @@ struct drm_mode_config {
>  	struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
>  	struct mutex idr_mutex; /* for IDR management */
>  	struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
> +	struct idr tile_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
>  	/* this is limited to one for now */
>  
>  
> @@ -1106,6 +1115,13 @@ extern void drm_set_preferred_mode(struct drm_connector *connector,
>  extern int drm_edid_header_is_valid(const u8 *raw_edid);
>  extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid);
>  extern bool drm_edid_is_valid(struct edid *edid);
> +
> +extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
> +							 char topology[8]);
> +extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
> +					       char topology[8]);
> +extern void drm_mode_put_tile_group(struct drm_device *dev,
> +				   struct drm_tile_group *tg);
>  struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
>  					   int hsize, int vsize, int fresh,
>  					   bool rb);
> -- 
> 2.1.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
Dave Airlie Oct. 28, 2014, 6:54 a.m. UTC | #2
> @@ -5156,3 +5158,100 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
>                                            supported_rotations);
>  }
>  EXPORT_SYMBOL(drm_mode_create_rotation_property);
> +
> +/**
> + * DOC: Tile group
> + *
> + * Tile groups are used to represent tiled monitors with a unique
> + * integer identifier. Tiled monitors using DisplayID v1.3 have
> + * a unique 8-byte handle, we store this in a tile group, so we
> + * have a common identifier for all tiles in a monitor group.
> + */
> +static void drm_tile_group_free(struct kref *kref)
> +{
> +       struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
> +       struct drm_device *dev = tg->dev;
> +       mutex_lock(&dev->mode_config.idr_mutex);
> +       idr_remove(&dev->mode_config.tile_idr, tg->id);
> +       mutex_lock(&dev->mode_config.idr_mutex);

Review not to self:

*un*lock.

Dave.
diff mbox

Patch

diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 0a5cbbb..5ea6289 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -2374,6 +2374,10 @@  void intel_crt_init(struct drm_device *dev)
       <title id="drm-kms-planehelpers">Plane Helper Reference</title>
 !Edrivers/gpu/drm/drm_plane_helper.c Plane Helpers
     </sect2>
+    <sect2>
+	  <title>Tile group</title>
+!Pdrivers/gpu/drm/drm_crtc.c Tile group
+    </sect2>
   </sect1>
 
   <!-- Internals: kms properties -->
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 363301c..7f45fdc 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -5047,6 +5047,7 @@  void drm_mode_config_init(struct drm_device *dev)
 	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
 	INIT_LIST_HEAD(&dev->mode_config.plane_list);
 	idr_init(&dev->mode_config.crtc_idr);
+	idr_init(&dev->mode_config.tile_idr);
 
 	drm_modeset_lock_all(dev);
 	drm_mode_create_standard_connector_properties(dev);
@@ -5134,6 +5135,7 @@  void drm_mode_config_cleanup(struct drm_device *dev)
 		crtc->funcs->destroy(crtc);
 	}
 
+	idr_destroy(&dev->mode_config.tile_idr);
 	idr_destroy(&dev->mode_config.crtc_idr);
 	drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
 }
@@ -5156,3 +5158,100 @@  struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
 					   supported_rotations);
 }
 EXPORT_SYMBOL(drm_mode_create_rotation_property);
+
+/**
+ * DOC: Tile group
+ *
+ * Tile groups are used to represent tiled monitors with a unique
+ * integer identifier. Tiled monitors using DisplayID v1.3 have
+ * a unique 8-byte handle, we store this in a tile group, so we
+ * have a common identifier for all tiles in a monitor group.
+ */
+static void drm_tile_group_free(struct kref *kref)
+{
+	struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
+	struct drm_device *dev = tg->dev;
+	mutex_lock(&dev->mode_config.idr_mutex);
+	idr_remove(&dev->mode_config.tile_idr, tg->id);
+	mutex_lock(&dev->mode_config.idr_mutex);
+	kfree(tg);
+}
+
+/**
+ * drm_mode_put_tile_group - drop a reference to a tile group.
+ * @dev: DRM device
+ * @tg: tile group to drop reference to.
+ *
+ * drop reference to tile group and free if 0.
+ */
+void drm_mode_put_tile_group(struct drm_device *dev,
+			     struct drm_tile_group *tg)
+{
+	kref_put(&tg->refcount, drm_tile_group_free);
+}
+
+/**
+ * drm_mode_get_tile_group - get a reference to an existing tile group
+ * @dev: DRM device
+ * @topology: 8-bytes unique per monitor.
+ *
+ * Use the unique bytes to get a reference to an existing tile group.
+ *
+ * RETURNS:
+ * tile group or NULL if not found.
+ */
+struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
+					       char topology[8])
+{
+	struct drm_tile_group *tg;
+	int id;
+	mutex_lock(&dev->mode_config.idr_mutex);
+	idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
+		if (!memcmp(tg->group_data, topology, 8)) {
+			if (!kref_get_unless_zero(&tg->refcount))
+				tg = NULL;
+			mutex_unlock(&dev->mode_config.idr_mutex);
+			return tg;
+		}
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+	return NULL;
+}
+
+/**
+ * drm_mode_create_tile_group - create a tile group from a displayid description
+ * @dev: DRM device
+ * @topology: 8-bytes unique per monitor.
+ *
+ * Create a tile group for the unique monitor, and get a unique
+ * identifier for the tile group.
+ *
+ * RETURNS:
+ * new tile group or error.
+ */
+struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
+						  char topology[8])
+{
+	struct drm_tile_group *tg;
+	int ret;
+
+	tg = kzalloc(sizeof(*tg), GFP_KERNEL);
+	if (!tg)
+		return ERR_PTR(-ENOMEM);
+
+	kref_init(&tg->refcount);
+	memcpy(tg->group_data, topology, 8);
+	tg->dev = dev;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
+	if (ret >= 0) {
+		tg->id = ret;
+	} else {
+		kfree(tg);
+		tg = ERR_PTR(ret);
+	}
+
+	mutex_unlock(&dev->mode_config.idr_mutex);
+	return tg;
+}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index f1105d0..afaec4b 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -136,6 +136,14 @@  struct drm_display_info {
 	u8 cea_rev;
 };
 
+/* data corresponds to displayid vend/prod/serial */
+struct drm_tile_group {
+	struct kref refcount;
+	struct drm_device *dev;
+	int id;
+	u8 group_data[8];
+};
+
 struct drm_framebuffer_funcs {
 	/* note: use drm_framebuffer_remove() */
 	void (*destroy)(struct drm_framebuffer *framebuffer);
@@ -770,6 +778,7 @@  struct drm_mode_config {
 	struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
 	struct mutex idr_mutex; /* for IDR management */
 	struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
+	struct idr tile_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
 	/* this is limited to one for now */
 
 
@@ -1106,6 +1115,13 @@  extern void drm_set_preferred_mode(struct drm_connector *connector,
 extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
+
+extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
+							 char topology[8]);
+extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
+					       char topology[8]);
+extern void drm_mode_put_tile_group(struct drm_device *dev,
+				   struct drm_tile_group *tg);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh,
 					   bool rb);