aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-10-20 02:17:17 -0400
committerDave Airlie <airlied@redhat.com>2014-12-08 18:56:46 -0500
commit138f9ebb9755a8cf09fd6a9ff8d011aaf5fb478f (patch)
tree167bcb1d1c10d7ea77ac084399698c7ad7c616ac
parentb49b55bd4fba6aa9bb25459e0ac3991c60c4aba4 (diff)
drm: add tile_group support. (v3)
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. v3: fix missing unlock. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--Documentation/DocBook/drm.tmpl4
-rw-r--r--drivers/gpu/drm/drm_crtc.c99
-rw-r--r--include/drm/drm_crtc.h16
3 files changed, 119 insertions, 0 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 56e2a9b65c68..bc4b5ab5848e 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -2412,6 +2412,10 @@ void intel_crt_init(struct drm_device *dev)
2412!Edrivers/gpu/drm/drm_plane_helper.c 2412!Edrivers/gpu/drm/drm_plane_helper.c
2413!Pdrivers/gpu/drm/drm_plane_helper.c overview 2413!Pdrivers/gpu/drm/drm_plane_helper.c overview
2414 </sect2> 2414 </sect2>
2415 <sect2>
2416 <title>Tile group</title>
2417!Pdrivers/gpu/drm/drm_crtc.c Tile group
2418 </sect2>
2415 </sect1> 2419 </sect1>
2416 2420
2417 <!-- Internals: kms properties --> 2421 <!-- Internals: kms properties -->
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index de79283eaea7..0d1eaa9966e9 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -5152,6 +5152,7 @@ void drm_mode_config_init(struct drm_device *dev)
5152 INIT_LIST_HEAD(&dev->mode_config.property_blob_list); 5152 INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
5153 INIT_LIST_HEAD(&dev->mode_config.plane_list); 5153 INIT_LIST_HEAD(&dev->mode_config.plane_list);
5154 idr_init(&dev->mode_config.crtc_idr); 5154 idr_init(&dev->mode_config.crtc_idr);
5155 idr_init(&dev->mode_config.tile_idr);
5155 5156
5156 drm_modeset_lock_all(dev); 5157 drm_modeset_lock_all(dev);
5157 drm_mode_create_standard_connector_properties(dev); 5158 drm_mode_create_standard_connector_properties(dev);
@@ -5239,6 +5240,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
5239 crtc->funcs->destroy(crtc); 5240 crtc->funcs->destroy(crtc);
5240 } 5241 }
5241 5242
5243 idr_destroy(&dev->mode_config.tile_idr);
5242 idr_destroy(&dev->mode_config.crtc_idr); 5244 idr_destroy(&dev->mode_config.crtc_idr);
5243 drm_modeset_lock_fini(&dev->mode_config.connection_mutex); 5245 drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
5244} 5246}
@@ -5261,3 +5263,100 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
5261 supported_rotations); 5263 supported_rotations);
5262} 5264}
5263EXPORT_SYMBOL(drm_mode_create_rotation_property); 5265EXPORT_SYMBOL(drm_mode_create_rotation_property);
5266
5267/**
5268 * DOC: Tile group
5269 *
5270 * Tile groups are used to represent tiled monitors with a unique
5271 * integer identifier. Tiled monitors using DisplayID v1.3 have
5272 * a unique 8-byte handle, we store this in a tile group, so we
5273 * have a common identifier for all tiles in a monitor group.
5274 */
5275static void drm_tile_group_free(struct kref *kref)
5276{
5277 struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
5278 struct drm_device *dev = tg->dev;
5279 mutex_lock(&dev->mode_config.idr_mutex);
5280 idr_remove(&dev->mode_config.tile_idr, tg->id);
5281 mutex_unlock(&dev->mode_config.idr_mutex);
5282 kfree(tg);
5283}
5284
5285/**
5286 * drm_mode_put_tile_group - drop a reference to a tile group.
5287 * @dev: DRM device
5288 * @tg: tile group to drop reference to.
5289 *
5290 * drop reference to tile group and free if 0.
5291 */
5292void drm_mode_put_tile_group(struct drm_device *dev,
5293 struct drm_tile_group *tg)
5294{
5295 kref_put(&tg->refcount, drm_tile_group_free);
5296}
5297
5298/**
5299 * drm_mode_get_tile_group - get a reference to an existing tile group
5300 * @dev: DRM device
5301 * @topology: 8-bytes unique per monitor.
5302 *
5303 * Use the unique bytes to get a reference to an existing tile group.
5304 *
5305 * RETURNS:
5306 * tile group or NULL if not found.
5307 */
5308struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
5309 char topology[8])
5310{
5311 struct drm_tile_group *tg;
5312 int id;
5313 mutex_lock(&dev->mode_config.idr_mutex);
5314 idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
5315 if (!memcmp(tg->group_data, topology, 8)) {
5316 if (!kref_get_unless_zero(&tg->refcount))
5317 tg = NULL;
5318 mutex_unlock(&dev->mode_config.idr_mutex);
5319 return tg;
5320 }
5321 }
5322 mutex_unlock(&dev->mode_config.idr_mutex);
5323 return NULL;
5324}
5325
5326/**
5327 * drm_mode_create_tile_group - create a tile group from a displayid description
5328 * @dev: DRM device
5329 * @topology: 8-bytes unique per monitor.
5330 *
5331 * Create a tile group for the unique monitor, and get a unique
5332 * identifier for the tile group.
5333 *
5334 * RETURNS:
5335 * new tile group or error.
5336 */
5337struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
5338 char topology[8])
5339{
5340 struct drm_tile_group *tg;
5341 int ret;
5342
5343 tg = kzalloc(sizeof(*tg), GFP_KERNEL);
5344 if (!tg)
5345 return ERR_PTR(-ENOMEM);
5346
5347 kref_init(&tg->refcount);
5348 memcpy(tg->group_data, topology, 8);
5349 tg->dev = dev;
5350
5351 mutex_lock(&dev->mode_config.idr_mutex);
5352 ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
5353 if (ret >= 0) {
5354 tg->id = ret;
5355 } else {
5356 kfree(tg);
5357 tg = ERR_PTR(ret);
5358 }
5359
5360 mutex_unlock(&dev->mode_config.idr_mutex);
5361 return tg;
5362}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index dd2c16e43333..8f760a2373f9 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -137,6 +137,14 @@ struct drm_display_info {
137 u8 cea_rev; 137 u8 cea_rev;
138}; 138};
139 139
140/* data corresponds to displayid vend/prod/serial */
141struct drm_tile_group {
142 struct kref refcount;
143 struct drm_device *dev;
144 int id;
145 u8 group_data[8];
146};
147
140struct drm_framebuffer_funcs { 148struct drm_framebuffer_funcs {
141 /* note: use drm_framebuffer_remove() */ 149 /* note: use drm_framebuffer_remove() */
142 void (*destroy)(struct drm_framebuffer *framebuffer); 150 void (*destroy)(struct drm_framebuffer *framebuffer);
@@ -978,6 +986,7 @@ struct drm_mode_config {
978 struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */ 986 struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
979 struct mutex idr_mutex; /* for IDR management */ 987 struct mutex idr_mutex; /* for IDR management */
980 struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ 988 struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
989 struct idr tile_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
981 /* this is limited to one for now */ 990 /* this is limited to one for now */
982 991
983 struct mutex fb_lock; /* proctects global and per-file fb lists */ 992 struct mutex fb_lock; /* proctects global and per-file fb lists */
@@ -1326,6 +1335,13 @@ extern void drm_set_preferred_mode(struct drm_connector *connector,
1326extern int drm_edid_header_is_valid(const u8 *raw_edid); 1335extern int drm_edid_header_is_valid(const u8 *raw_edid);
1327extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid); 1336extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid);
1328extern bool drm_edid_is_valid(struct edid *edid); 1337extern bool drm_edid_is_valid(struct edid *edid);
1338
1339extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
1340 char topology[8]);
1341extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
1342 char topology[8]);
1343extern void drm_mode_put_tile_group(struct drm_device *dev,
1344 struct drm_tile_group *tg);
1329struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, 1345struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
1330 int hsize, int vsize, int fresh, 1346 int hsize, int vsize, int fresh,
1331 bool rb); 1347 bool rb);