hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/gpu/drm/drm_client.c
....@@ -1,4 +1,4 @@
1
-// SPDX-License-Identifier: GPL-2.0
1
+// SPDX-License-Identifier: GPL-2.0 or MIT
22 /*
33 * Copyright 2018 Noralf Trønnes
44 */
....@@ -15,10 +15,10 @@
1515 #include <drm/drm_drv.h>
1616 #include <drm/drm_file.h>
1717 #include <drm/drm_fourcc.h>
18
+#include <drm/drm_framebuffer.h>
1819 #include <drm/drm_gem.h>
1920 #include <drm/drm_mode.h>
2021 #include <drm/drm_print.h>
21
-#include <drm/drmP.h>
2222
2323 #include "drm_crtc_internal.h"
2424 #include "drm_internal.h"
....@@ -27,7 +27,6 @@
2727 * DOC: overview
2828 *
2929 * This library provides support for clients running in the kernel like fbdev and bootsplash.
30
- * Currently it's only partially implemented, just enough to support fbdev.
3130 *
3231 * GEM drivers which provide a GEM based dumb buffer with a virtual address are supported.
3332 */
....@@ -68,7 +67,8 @@
6867 * @name: Client name
6968 * @funcs: DRM client functions (optional)
7069 *
71
- * This initialises the client and opens a &drm_file. Use drm_client_add() to complete the process.
70
+ * This initialises the client and opens a &drm_file.
71
+ * Use drm_client_register() to complete the process.
7272 * The caller needs to hold a reference on @dev before calling this function.
7373 * The client is freed when the &drm_device is unregistered. See drm_client_release().
7474 *
....@@ -80,9 +80,8 @@
8080 {
8181 int ret;
8282
83
- if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
84
- !dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
85
- return -ENOTSUPP;
83
+ if (!drm_core_check_feature(dev, DRIVER_MODESET) || !dev->driver->dumb_create)
84
+ return -EOPNOTSUPP;
8685
8786 if (funcs && !try_module_get(funcs->owner))
8887 return -ENODEV;
....@@ -91,14 +90,20 @@
9190 client->name = name;
9291 client->funcs = funcs;
9392
94
- ret = drm_client_open(client);
93
+ ret = drm_client_modeset_create(client);
9594 if (ret)
9695 goto err_put_module;
96
+
97
+ ret = drm_client_open(client);
98
+ if (ret)
99
+ goto err_free;
97100
98101 drm_dev_get(dev);
99102
100103 return 0;
101104
105
+err_free:
106
+ drm_client_modeset_free(client);
102107 err_put_module:
103108 if (funcs)
104109 module_put(funcs->owner);
....@@ -108,16 +113,16 @@
108113 EXPORT_SYMBOL(drm_client_init);
109114
110115 /**
111
- * drm_client_add - Add client to the device list
116
+ * drm_client_register - Register client
112117 * @client: DRM client
113118 *
114119 * Add the client to the &drm_device client list to activate its callbacks.
115120 * @client must be initialized by a call to drm_client_init(). After
116
- * drm_client_add() it is no longer permissible to call drm_client_release()
121
+ * drm_client_register() it is no longer permissible to call drm_client_release()
117122 * directly (outside the unregister callback), instead cleanup will happen
118123 * automatically on driver unload.
119124 */
120
-void drm_client_add(struct drm_client_dev *client)
125
+void drm_client_register(struct drm_client_dev *client)
121126 {
122127 struct drm_device *dev = client->dev;
123128
....@@ -125,7 +130,7 @@
125130 list_add(&client->list, &dev->clientlist);
126131 mutex_unlock(&dev->clientlist_mutex);
127132 }
128
-EXPORT_SYMBOL(drm_client_add);
133
+EXPORT_SYMBOL(drm_client_register);
129134
130135 /**
131136 * drm_client_release - Release DRM client resources
....@@ -145,8 +150,9 @@
145150 {
146151 struct drm_device *dev = client->dev;
147152
148
- DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
153
+ drm_dbg_kms(dev, "%s\n", client->name);
149154
155
+ drm_client_modeset_free(client);
150156 drm_client_close(client);
151157 drm_dev_put(dev);
152158 if (client->funcs)
....@@ -197,7 +203,7 @@
197203 continue;
198204
199205 ret = client->funcs->hotplug(client);
200
- DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
206
+ drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
201207 }
202208 mutex_unlock(&dev->clientlist_mutex);
203209 }
....@@ -217,7 +223,7 @@
217223 continue;
218224
219225 ret = client->funcs->restore(client);
220
- DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
226
+ drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
221227 if (!ret) /* The first one to return zero gets the privilege to restore */
222228 break;
223229 }
....@@ -228,11 +234,10 @@
228234 {
229235 struct drm_device *dev = buffer->client->dev;
230236
231
- if (buffer->vaddr && dev->driver->gem_prime_vunmap)
232
- dev->driver->gem_prime_vunmap(buffer->gem, buffer->vaddr);
237
+ drm_gem_vunmap(buffer->gem, buffer->vaddr);
233238
234239 if (buffer->gem)
235
- drm_gem_object_put_unlocked(buffer->gem);
240
+ drm_gem_object_put(buffer->gem);
236241
237242 if (buffer->handle)
238243 drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file);
....@@ -243,11 +248,11 @@
243248 static struct drm_client_buffer *
244249 drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
245250 {
251
+ const struct drm_format_info *info = drm_format_info(format);
246252 struct drm_mode_create_dumb dumb_args = { };
247253 struct drm_device *dev = client->dev;
248254 struct drm_client_buffer *buffer;
249255 struct drm_gem_object *obj;
250
- void *vaddr;
251256 int ret;
252257
253258 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
....@@ -258,7 +263,7 @@
258263
259264 dumb_args.width = width;
260265 dumb_args.height = height;
261
- dumb_args.bpp = drm_format_plane_cpp(format, 0) * 8;
266
+ dumb_args.bpp = info->cpp[0] * 8;
262267 ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
263268 if (ret)
264269 goto err_delete;
....@@ -274,6 +279,36 @@
274279
275280 buffer->gem = obj;
276281
282
+ return buffer;
283
+
284
+err_delete:
285
+ drm_client_buffer_delete(buffer);
286
+
287
+ return ERR_PTR(ret);
288
+}
289
+
290
+/**
291
+ * drm_client_buffer_vmap - Map DRM client buffer into address space
292
+ * @buffer: DRM client buffer
293
+ *
294
+ * This function maps a client buffer into kernel address space. If the
295
+ * buffer is already mapped, it returns the mapping's address.
296
+ *
297
+ * Client buffer mappings are not ref'counted. Each call to
298
+ * drm_client_buffer_vmap() should be followed by a call to
299
+ * drm_client_buffer_vunmap(); or the client buffer should be mapped
300
+ * throughout its lifetime.
301
+ *
302
+ * Returns:
303
+ * The mapped memory's address
304
+ */
305
+void *drm_client_buffer_vmap(struct drm_client_buffer *buffer)
306
+{
307
+ void *vaddr;
308
+
309
+ if (buffer->vaddr)
310
+ return buffer->vaddr;
311
+
277312 /*
278313 * FIXME: The dependency on GEM here isn't required, we could
279314 * convert the driver handle to a dma-buf instead and use the
....@@ -282,21 +317,30 @@
282317 * fd_install step out of the driver backend hooks, to make that
283318 * final step optional for internal users.
284319 */
285
- vaddr = dev->driver->gem_prime_vmap(obj);
286
- if (!vaddr) {
287
- ret = -ENOMEM;
288
- goto err_delete;
289
- }
320
+ vaddr = drm_gem_vmap(buffer->gem);
321
+ if (IS_ERR(vaddr))
322
+ return vaddr;
290323
291324 buffer->vaddr = vaddr;
292325
293
- return buffer;
294
-
295
-err_delete:
296
- drm_client_buffer_delete(buffer);
297
-
298
- return ERR_PTR(ret);
326
+ return vaddr;
299327 }
328
+EXPORT_SYMBOL(drm_client_buffer_vmap);
329
+
330
+/**
331
+ * drm_client_buffer_vunmap - Unmap DRM client buffer
332
+ * @buffer: DRM client buffer
333
+ *
334
+ * This function removes a client buffer's memory mapping. Calling this
335
+ * function is only required by clients that manage their buffer mappings
336
+ * by themselves.
337
+ */
338
+void drm_client_buffer_vunmap(struct drm_client_buffer *buffer)
339
+{
340
+ drm_gem_vunmap(buffer->gem, buffer->vaddr);
341
+ buffer->vaddr = NULL;
342
+}
343
+EXPORT_SYMBOL(drm_client_buffer_vunmap);
300344
301345 static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
302346 {
....@@ -307,8 +351,8 @@
307351
308352 ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file);
309353 if (ret)
310
- DRM_DEV_ERROR(buffer->client->dev->dev,
311
- "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
354
+ drm_err(buffer->client->dev,
355
+ "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
312356
313357 buffer->fb = NULL;
314358 }
....@@ -322,7 +366,7 @@
322366 int ret;
323367
324368 info = drm_format_info(format);
325
- fb_req.bpp = info->bpp[0];
369
+ fb_req.bpp = info->cpp[0] * 8;
326370 fb_req.depth = info->depth;
327371 fb_req.width = width;
328372 fb_req.height = height;
....@@ -393,6 +437,39 @@
393437 }
394438 EXPORT_SYMBOL(drm_client_framebuffer_delete);
395439
440
+/**
441
+ * drm_client_framebuffer_flush - Manually flush client framebuffer
442
+ * @buffer: DRM client buffer (can be NULL)
443
+ * @rect: Damage rectangle (if NULL flushes all)
444
+ *
445
+ * This calls &drm_framebuffer_funcs->dirty (if present) to flush buffer changes
446
+ * for drivers that need it.
447
+ *
448
+ * Returns:
449
+ * Zero on success or negative error code on failure.
450
+ */
451
+int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect)
452
+{
453
+ if (!buffer || !buffer->fb || !buffer->fb->funcs->dirty)
454
+ return 0;
455
+
456
+ if (rect) {
457
+ struct drm_clip_rect clip = {
458
+ .x1 = rect->x1,
459
+ .y1 = rect->y1,
460
+ .x2 = rect->x2,
461
+ .y2 = rect->y2,
462
+ };
463
+
464
+ return buffer->fb->funcs->dirty(buffer->fb, buffer->client->file,
465
+ 0, 0, &clip, 1);
466
+ }
467
+
468
+ return buffer->fb->funcs->dirty(buffer->fb, buffer->client->file,
469
+ 0, 0, NULL, 0);
470
+}
471
+EXPORT_SYMBOL(drm_client_framebuffer_flush);
472
+
396473 #ifdef CONFIG_DEBUG_FS
397474 static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)
398475 {
....@@ -413,10 +490,10 @@
413490 { "internal_clients", drm_client_debugfs_internal_clients, 0 },
414491 };
415492
416
-int drm_client_debugfs_init(struct drm_minor *minor)
493
+void drm_client_debugfs_init(struct drm_minor *minor)
417494 {
418
- return drm_debugfs_create_files(drm_client_debugfs_list,
419
- ARRAY_SIZE(drm_client_debugfs_list),
420
- minor->debugfs_root, minor);
495
+ drm_debugfs_create_files(drm_client_debugfs_list,
496
+ ARRAY_SIZE(drm_client_debugfs_list),
497
+ minor->debugfs_root, minor);
421498 }
422499 #endif