xref: /linux/drivers/gpu/drm/drm_writeback.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
4  * Author: Brian Starkey <brian.starkey@arm.com>
5  *
6  * This program is free software and is provided to you under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation, and any use by you of this program is subject to the terms
9  * of such GNU licence.
10  */
11 
12 #include <linux/dma-fence.h>
13 #include <linux/export.h>
14 
15 #include <drm/drm_crtc.h>
16 #include <drm/drm_device.h>
17 #include <drm/drm_drv.h>
18 #include <drm/drm_framebuffer.h>
19 #include <drm/drm_managed.h>
20 #include <drm/drm_modeset_helper_vtables.h>
21 #include <drm/drm_property.h>
22 #include <drm/drm_writeback.h>
23 
24 /**
25  * DOC: overview
26  *
27  * Writeback connectors are used to expose hardware which can write the output
28  * from a CRTC to a memory buffer. They are used and act similarly to other
29  * types of connectors, with some important differences:
30  *
31  * * Writeback connectors don't provide a way to output visually to the user.
32  *
33  * * Writeback connectors are visible to userspace only when the client sets
34  *   DRM_CLIENT_CAP_WRITEBACK_CONNECTORS.
35  *
36  * * Writeback connectors don't have EDID.
37  *
38  * A framebuffer may only be attached to a writeback connector when the
39  * connector is attached to a CRTC. The WRITEBACK_FB_ID property which sets the
40  * framebuffer applies only to a single commit (see below). A framebuffer may
41  * not be attached while the CRTC is off.
42  *
43  * Unlike with planes, when a writeback framebuffer is removed by userspace DRM
44  * makes no attempt to remove it from active use by the connector. This is
45  * because no method is provided to abort a writeback operation, and in any
46  * case making a new commit whilst a writeback is ongoing is undefined (see
47  * WRITEBACK_OUT_FENCE_PTR below). As soon as the current writeback is finished,
48  * the framebuffer will automatically no longer be in active use. As it will
49  * also have already been removed from the framebuffer list, there will be no
50  * way for any userspace application to retrieve a reference to it in the
51  * intervening period.
52  *
53  * Writeback connectors have some additional properties, which userspace
54  * can use to query and control them:
55  *
56  *  "WRITEBACK_FB_ID":
57  *	Write-only object property storing a DRM_MODE_OBJECT_FB: it stores the
58  *	framebuffer to be written by the writeback connector. This property is
59  *	similar to the FB_ID property on planes, but will always read as zero
60  *	and is not preserved across commits.
61  *	If the width and height of the framebuffer do not match those of the
62  *	attached CRTC, the driver must either fail or scale (not crop) the
63  *	content to exactly fit the framebuffer.
64  *	If the driver is unable to exactly fill the framebuffer for any reason,
65  *	such as hardware scaler constraints or an odd width for a sub-sampled
66  *	format, the writeback must fail instead of partially filling the buffer.
67  *	Userspace must set this property to an output buffer every time it
68  *	wishes the buffer to get filled.
69  *
70  *  "WRITEBACK_PIXEL_FORMATS":
71  *	Immutable blob property to store the supported pixel formats table. The
72  *	data is an array of u32 DRM_FORMAT_* fourcc values.
73  *	Userspace can use this blob to find out what pixel formats are supported
74  *	by the connector's writeback engine.
75  *
76  *  "WRITEBACK_OUT_FENCE_PTR":
77  *	Userspace can use this property to provide a pointer for the kernel to
78  *	fill with a sync_file file descriptor, which will signal once the
79  *	writeback is finished. The value should be the address of a 32-bit
80  *	signed integer, cast to a u64.
81  *	Userspace should wait for this fence to signal before making another
82  *	commit affecting any of the same CRTCs, Planes or Connectors.
83  *	**Failure to do so will result in undefined behaviour.**
84  *	For this reason it is strongly recommended that all userspace
85  *	applications making use of writeback connectors *always* retrieve an
86  *	out-fence for the commit and use it appropriately.
87  *	From userspace, this property will always read as zero.
88  */
89 
90 #define fence_to_wb_connector(x) container_of(x->extern_lock, \
91 					      struct drm_writeback_connector, \
92 					      fence_lock)
93 
94 static const char *drm_writeback_fence_get_driver_name(struct dma_fence *fence)
95 {
96 	struct drm_writeback_connector *wb_connector =
97 		fence_to_wb_connector(fence);
98 
99 	return wb_connector->base.dev->driver->name;
100 }
101 
102 static const char *
103 drm_writeback_fence_get_timeline_name(struct dma_fence *fence)
104 {
105 	struct drm_writeback_connector *wb_connector =
106 		fence_to_wb_connector(fence);
107 
108 	return wb_connector->timeline_name;
109 }
110 
111 static const struct dma_fence_ops drm_writeback_fence_ops = {
112 	.get_driver_name = drm_writeback_fence_get_driver_name,
113 	.get_timeline_name = drm_writeback_fence_get_timeline_name,
114 };
115 
116 static int create_writeback_properties(struct drm_device *dev)
117 {
118 	struct drm_property *prop;
119 
120 	if (!dev->mode_config.writeback_fb_id_property) {
121 		prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
122 						  "WRITEBACK_FB_ID",
123 						  DRM_MODE_OBJECT_FB);
124 		if (!prop)
125 			return -ENOMEM;
126 		dev->mode_config.writeback_fb_id_property = prop;
127 	}
128 
129 	if (!dev->mode_config.writeback_pixel_formats_property) {
130 		prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
131 					   DRM_MODE_PROP_ATOMIC |
132 					   DRM_MODE_PROP_IMMUTABLE,
133 					   "WRITEBACK_PIXEL_FORMATS", 0);
134 		if (!prop)
135 			return -ENOMEM;
136 		dev->mode_config.writeback_pixel_formats_property = prop;
137 	}
138 
139 	if (!dev->mode_config.writeback_out_fence_ptr_property) {
140 		prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
141 						 "WRITEBACK_OUT_FENCE_PTR", 0,
142 						 U64_MAX);
143 		if (!prop)
144 			return -ENOMEM;
145 		dev->mode_config.writeback_out_fence_ptr_property = prop;
146 	}
147 
148 	return 0;
149 }
150 
151 static const struct drm_encoder_funcs drm_writeback_encoder_funcs = {
152 	.destroy = drm_encoder_cleanup,
153 };
154 
155 /**
156  * drm_writeback_connector_init - Initialize a writeback connector and its properties
157  * @dev: DRM device
158  * @wb_connector: Writeback connector to initialize
159  * @con_funcs: Connector funcs vtable
160  * @enc_helper_funcs: Encoder helper funcs vtable to be used by the internal encoder
161  * @formats: Array of supported pixel formats for the writeback engine
162  * @n_formats: Length of the formats array
163  * @possible_crtcs: possible crtcs for the internal writeback encoder
164  *
165  * This function creates the writeback-connector-specific properties if they
166  * have not been already created, initializes the connector as
167  * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
168  * values. It will also create an internal encoder associated with the
169  * drm_writeback_connector and set it to use the @enc_helper_funcs vtable for
170  * the encoder helper.
171  *
172  * Drivers should always use this function instead of drm_connector_init() to
173  * set up writeback connectors.
174  *
175  * Returns: 0 on success, or a negative error code
176  */
177 int drm_writeback_connector_init(struct drm_device *dev,
178 				 struct drm_writeback_connector *wb_connector,
179 				 const struct drm_connector_funcs *con_funcs,
180 				 const struct drm_encoder_helper_funcs *enc_helper_funcs,
181 				 const u32 *formats, int n_formats,
182 				 u32 possible_crtcs)
183 {
184 	int ret = 0;
185 
186 	drm_encoder_helper_add(&wb_connector->encoder, enc_helper_funcs);
187 
188 	wb_connector->encoder.possible_crtcs = possible_crtcs;
189 
190 	ret = drm_encoder_init(dev, &wb_connector->encoder,
191 			       &drm_writeback_encoder_funcs,
192 			       DRM_MODE_ENCODER_VIRTUAL, NULL);
193 	if (ret)
194 		return ret;
195 
196 	ret = drm_writeback_connector_init_with_encoder(dev, wb_connector, &wb_connector->encoder,
197 			con_funcs, formats, n_formats);
198 
199 	if (ret)
200 		drm_encoder_cleanup(&wb_connector->encoder);
201 
202 	return ret;
203 }
204 EXPORT_SYMBOL(drm_writeback_connector_init);
205 
206 static void delete_writeback_properties(struct drm_device *dev)
207 {
208 	if (dev->mode_config.writeback_pixel_formats_property) {
209 		drm_property_destroy(dev, dev->mode_config.writeback_pixel_formats_property);
210 		dev->mode_config.writeback_pixel_formats_property = NULL;
211 	}
212 	if (dev->mode_config.writeback_out_fence_ptr_property) {
213 		drm_property_destroy(dev, dev->mode_config.writeback_out_fence_ptr_property);
214 		dev->mode_config.writeback_out_fence_ptr_property = NULL;
215 	}
216 	if (dev->mode_config.writeback_fb_id_property) {
217 		drm_property_destroy(dev, dev->mode_config.writeback_fb_id_property);
218 		dev->mode_config.writeback_fb_id_property = NULL;
219 	}
220 }
221 
222 /**
223  * __drm_writeback_connector_init - Initialize a writeback connector with
224  * a custom encoder
225  *
226  * @dev: DRM device
227  * @wb_connector: Writeback connector to initialize
228  * @enc: handle to the already initialized drm encoder
229  * @formats: Array of supported pixel formats for the writeback engine
230  * @n_formats: Length of the formats array
231  *
232  * This function creates the writeback-connector-specific properties if they
233  * have not been already created, initializes the connector as
234  * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
235  * values.
236  *
237  * This function assumes that the drm_writeback_connector's encoder has already been
238  * created and initialized before invoking this function.
239  *
240  * In addition, this function also assumes that callers of this API will manage
241  * assigning the encoder helper functions, possible_crtcs and any other encoder
242  * specific operation.
243  *
244  * Returns: 0 on success, or a negative error code
245  */
246 static int __drm_writeback_connector_init(struct drm_device *dev,
247 					  struct drm_writeback_connector *wb_connector,
248 					  struct drm_encoder *enc, const u32 *formats,
249 					  int n_formats)
250 {
251 	struct drm_connector *connector = &wb_connector->base;
252 	struct drm_mode_config *config = &dev->mode_config;
253 	struct drm_property_blob *blob;
254 	int ret = create_writeback_properties(dev);
255 
256 	if (ret != 0)
257 		goto failed_properties;
258 
259 	connector->interlace_allowed = 0;
260 
261 	ret = drm_connector_attach_encoder(connector, enc);
262 	if (ret)
263 		goto failed_properties;
264 
265 	blob = drm_property_create_blob(dev, n_formats * sizeof(*formats),
266 					formats);
267 	if (IS_ERR(blob)) {
268 		ret = PTR_ERR(blob);
269 		goto failed_properties;
270 	}
271 
272 	INIT_LIST_HEAD(&wb_connector->job_queue);
273 	spin_lock_init(&wb_connector->job_lock);
274 
275 	wb_connector->fence_context = dma_fence_context_alloc(1);
276 	spin_lock_init(&wb_connector->fence_lock);
277 	snprintf(wb_connector->timeline_name,
278 		 sizeof(wb_connector->timeline_name),
279 		 "CONNECTOR:%d-%s", connector->base.id, connector->name);
280 
281 	drm_object_attach_property(&connector->base,
282 				   config->writeback_out_fence_ptr_property, 0);
283 
284 	drm_object_attach_property(&connector->base,
285 				   config->writeback_fb_id_property, 0);
286 
287 	drm_object_attach_property(&connector->base,
288 				   config->writeback_pixel_formats_property,
289 				   blob->base.id);
290 	wb_connector->pixel_formats_blob_ptr = blob;
291 
292 	return 0;
293 failed_properties:
294 	delete_writeback_properties(dev);
295 	return ret;
296 }
297 
298 /**
299  * drm_writeback_connector_init_with_encoder - Initialize a writeback connector with
300  * a custom encoder
301  *
302  * @dev: DRM device
303  * @wb_connector: Writeback connector to initialize
304  * @enc: handle to the already initialized drm encoder
305  * @con_funcs: Connector funcs vtable
306  * @formats: Array of supported pixel formats for the writeback engine
307  * @n_formats: Length of the formats array
308  *
309  * This function creates the writeback-connector-specific properties if they
310  * have not been already created, initializes the connector as
311  * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
312  * values.
313  *
314  * This function assumes that the drm_writeback_connector's encoder has already been
315  * created and initialized before invoking this function.
316  *
317  * In addition, this function also assumes that callers of this API will manage
318  * assigning the encoder helper functions, possible_crtcs and any other encoder
319  * specific operation.
320  *
321  * Drivers should always use this function instead of drm_connector_init() to
322  * set up writeback connectors if they want to manage themselves the lifetime of the
323  * associated encoder.
324  *
325  * Returns: 0 on success, or a negative error code
326  */
327 int drm_writeback_connector_init_with_encoder(struct drm_device *dev,
328 					      struct drm_writeback_connector *wb_connector,
329 					      struct drm_encoder *enc,
330 					      const struct drm_connector_funcs *con_funcs,
331 					      const u32 *formats, int n_formats)
332 {
333 	struct drm_connector *connector = &wb_connector->base;
334 	int ret;
335 
336 	ret = drm_connector_init(dev, connector, con_funcs,
337 				 DRM_MODE_CONNECTOR_WRITEBACK);
338 	if (ret)
339 		return ret;
340 
341 	ret = __drm_writeback_connector_init(dev, wb_connector, enc, formats,
342 					     n_formats);
343 	if (ret)
344 		drm_connector_cleanup(connector);
345 
346 	return ret;
347 }
348 EXPORT_SYMBOL(drm_writeback_connector_init_with_encoder);
349 
350 /**
351  * drm_writeback_connector_cleanup - Cleanup the writeback connector
352  * @dev: DRM device
353  * @data: Pointer to the writeback connector to clean up
354  *
355  * This will decrement the reference counter of blobs and destroy properties. It
356  * will also clean the remaining jobs in this writeback connector. Caution: This helper will not
357  * clean up the attached encoder and the drm_connector.
358  */
359 static void drm_writeback_connector_cleanup(struct drm_device *dev,
360 					    void *data)
361 {
362 	unsigned long flags;
363 	struct drm_writeback_job *pos, *n;
364 	struct drm_writeback_connector *wb_connector = data;
365 
366 	delete_writeback_properties(dev);
367 	drm_property_blob_put(wb_connector->pixel_formats_blob_ptr);
368 
369 	spin_lock_irqsave(&wb_connector->job_lock, flags);
370 	list_for_each_entry_safe(pos, n, &wb_connector->job_queue, list_entry) {
371 		list_del(&pos->list_entry);
372 		drm_writeback_cleanup_job(pos);
373 	}
374 	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
375 }
376 
377 /**
378  * drmm_writeback_connector_init - Initialize a writeback connector with
379  * a custom encoder
380  *
381  * @dev: DRM device
382  * @wb_connector: Writeback connector to initialize
383  * @con_funcs: Connector funcs vtable
384  * @enc: Encoder to connect this writeback connector
385  * @formats: Array of supported pixel formats for the writeback engine
386  * @n_formats: Length of the formats array
387  *
388  * This function initialize a writeback connector and register its cleanup.
389  *
390  * This function creates the writeback-connector-specific properties if they
391  * have not been already created, initializes the connector as
392  * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
393  * values.
394  *
395  * Returns: 0 on success, or a negative error code
396  */
397 int drmm_writeback_connector_init(struct drm_device *dev,
398 				  struct drm_writeback_connector *wb_connector,
399 				  const struct drm_connector_funcs *con_funcs,
400 				  struct drm_encoder *enc,
401 				  const u32 *formats, int n_formats)
402 {
403 	struct drm_connector *connector = &wb_connector->base;
404 	int ret;
405 
406 	ret = drmm_connector_init(dev, connector, con_funcs,
407 				  DRM_MODE_CONNECTOR_WRITEBACK, NULL);
408 	if (ret)
409 		return ret;
410 
411 	ret = __drm_writeback_connector_init(dev, wb_connector, enc, formats,
412 					     n_formats);
413 	if (ret)
414 		return ret;
415 
416 	ret = drmm_add_action_or_reset(dev, drm_writeback_connector_cleanup,
417 				       wb_connector);
418 	if (ret)
419 		return ret;
420 
421 	return 0;
422 }
423 EXPORT_SYMBOL(drmm_writeback_connector_init);
424 
425 int drm_writeback_set_fb(struct drm_connector_state *conn_state,
426 			 struct drm_framebuffer *fb)
427 {
428 	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
429 
430 	if (!conn_state->writeback_job) {
431 		conn_state->writeback_job = kzalloc_obj(*conn_state->writeback_job);
432 		if (!conn_state->writeback_job)
433 			return -ENOMEM;
434 
435 		conn_state->writeback_job->connector =
436 			drm_connector_to_writeback(conn_state->connector);
437 	}
438 
439 	drm_framebuffer_assign(&conn_state->writeback_job->fb, fb);
440 	return 0;
441 }
442 
443 int drm_writeback_prepare_job(struct drm_writeback_job *job)
444 {
445 	struct drm_writeback_connector *connector = job->connector;
446 	const struct drm_connector_helper_funcs *funcs =
447 		connector->base.helper_private;
448 	int ret;
449 
450 	if (funcs->prepare_writeback_job) {
451 		ret = funcs->prepare_writeback_job(connector, job);
452 		if (ret < 0)
453 			return ret;
454 	}
455 
456 	job->prepared = true;
457 	return 0;
458 }
459 EXPORT_SYMBOL(drm_writeback_prepare_job);
460 
461 /**
462  * drm_writeback_queue_job - Queue a writeback job for later signalling
463  * @wb_connector: The writeback connector to queue a job on
464  * @conn_state: The connector state containing the job to queue
465  *
466  * This function adds the job contained in @conn_state to the job_queue for a
467  * writeback connector. It takes ownership of the writeback job and sets the
468  * @conn_state->writeback_job to NULL, and so no access to the job may be
469  * performed by the caller after this function returns.
470  *
471  * Drivers must ensure that for a given writeback connector, jobs are queued in
472  * exactly the same order as they will be completed by the hardware (and
473  * signaled via drm_writeback_signal_completion).
474  *
475  * For every call to drm_writeback_queue_job() there must be exactly one call to
476  * drm_writeback_signal_completion()
477  *
478  * See also: drm_writeback_signal_completion()
479  */
480 void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector,
481 			     struct drm_connector_state *conn_state)
482 {
483 	struct drm_writeback_job *job;
484 	unsigned long flags;
485 
486 	job = conn_state->writeback_job;
487 	conn_state->writeback_job = NULL;
488 
489 	spin_lock_irqsave(&wb_connector->job_lock, flags);
490 	list_add_tail(&job->list_entry, &wb_connector->job_queue);
491 	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
492 }
493 EXPORT_SYMBOL(drm_writeback_queue_job);
494 
495 void drm_writeback_cleanup_job(struct drm_writeback_job *job)
496 {
497 	struct drm_writeback_connector *connector = job->connector;
498 	const struct drm_connector_helper_funcs *funcs =
499 		connector->base.helper_private;
500 
501 	if (job->prepared && funcs->cleanup_writeback_job)
502 		funcs->cleanup_writeback_job(connector, job);
503 
504 	if (job->fb)
505 		drm_framebuffer_put(job->fb);
506 
507 	if (job->out_fence)
508 		dma_fence_put(job->out_fence);
509 
510 	kfree(job);
511 }
512 EXPORT_SYMBOL(drm_writeback_cleanup_job);
513 
514 /*
515  * @cleanup_work: deferred cleanup of a writeback job
516  *
517  * The job cannot be cleaned up directly in drm_writeback_signal_completion,
518  * because it may be called in interrupt context. Dropping the framebuffer
519  * reference can sleep, and so the cleanup is deferred to a workqueue.
520  */
521 static void cleanup_work(struct work_struct *work)
522 {
523 	struct drm_writeback_job *job = container_of(work,
524 						     struct drm_writeback_job,
525 						     cleanup_work);
526 
527 	drm_writeback_cleanup_job(job);
528 }
529 
530 /**
531  * drm_writeback_signal_completion - Signal the completion of a writeback job
532  * @wb_connector: The writeback connector whose job is complete
533  * @status: Status code to set in the writeback out_fence (0 for success)
534  *
535  * Drivers should call this to signal the completion of a previously queued
536  * writeback job. It should be called as soon as possible after the hardware
537  * has finished writing, and may be called from interrupt context.
538  * It is the driver's responsibility to ensure that for a given connector, the
539  * hardware completes writeback jobs in the same order as they are queued.
540  *
541  * Unless the driver is holding its own reference to the framebuffer, it must
542  * not be accessed after calling this function.
543  *
544  * See also: drm_writeback_queue_job()
545  */
546 void
547 drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector,
548 				int status)
549 {
550 	unsigned long flags;
551 	struct drm_writeback_job *job;
552 	struct dma_fence *out_fence;
553 
554 	spin_lock_irqsave(&wb_connector->job_lock, flags);
555 	job = list_first_entry_or_null(&wb_connector->job_queue,
556 				       struct drm_writeback_job,
557 				       list_entry);
558 	if (job)
559 		list_del(&job->list_entry);
560 
561 	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
562 
563 	if (WARN_ON(!job))
564 		return;
565 
566 	out_fence = job->out_fence;
567 	if (out_fence) {
568 		if (status)
569 			dma_fence_set_error(out_fence, status);
570 		dma_fence_signal(out_fence);
571 		dma_fence_put(out_fence);
572 		job->out_fence = NULL;
573 	}
574 
575 	INIT_WORK(&job->cleanup_work, cleanup_work);
576 	queue_work(system_long_wq, &job->cleanup_work);
577 }
578 EXPORT_SYMBOL(drm_writeback_signal_completion);
579 
580 struct dma_fence *
581 drm_writeback_get_out_fence(struct drm_writeback_connector *wb_connector)
582 {
583 	struct dma_fence *fence;
584 
585 	if (WARN_ON(wb_connector->base.connector_type !=
586 		    DRM_MODE_CONNECTOR_WRITEBACK))
587 		return NULL;
588 
589 	fence = kzalloc_obj(*fence);
590 	if (!fence)
591 		return NULL;
592 
593 	dma_fence_init(fence, &drm_writeback_fence_ops,
594 		       &wb_connector->fence_lock, wb_connector->fence_context,
595 		       ++wb_connector->fence_seqno);
596 
597 	return fence;
598 }
599 EXPORT_SYMBOL(drm_writeback_get_out_fence);
600