|
@@ -1121,3 +1121,107 @@ out_unlock:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 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. The property is called "TILE". Drivers can manage tile
|
|
|
|
+ * groups using drm_mode_create_tile_group(), drm_mode_put_tile_group() and
|
|
|
|
+ * drm_mode_get_tile_group(). But this is only needed for internal panels where
|
|
|
|
+ * the tile group information is exposed through a non-standard way.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+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_unlock(&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);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(drm_mode_put_tile_group);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 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;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(drm_mode_get_tile_group);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 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;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(drm_mode_create_tile_group);
|