Merge branch 'linux-linaro-lsk' into linux-linaro-lsk-android
[firefly-linux-kernel-4.4.55.git] / drivers / video / adf / adf_client.c
1 /*
2  * Copyright (C) 2013 Google, Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14
15 #include <linux/kthread.h>
16 #include <linux/mutex.h>
17 #include <linux/slab.h>
18
19 #include "sw_sync.h"
20
21 #include <video/adf.h>
22 #include <video/adf_client.h>
23 #include <video/adf_format.h>
24
25 #include "adf.h"
26
27 static inline bool vsync_active(u8 state)
28 {
29         return state == DRM_MODE_DPMS_ON || state == DRM_MODE_DPMS_STANDBY;
30 }
31
32 /**
33  * adf_interface_blank - set interface's DPMS state
34  *
35  * @intf: the interface
36  * @state: one of %DRM_MODE_DPMS_*
37  *
38  * Returns 0 on success or -errno on failure.
39  */
40 int adf_interface_blank(struct adf_interface *intf, u8 state)
41 {
42         struct adf_device *dev = adf_interface_parent(intf);
43         u8 prev_state;
44         bool disable_vsync;
45         bool enable_vsync;
46         int ret = 0;
47         struct adf_event_refcount *vsync_refcount;
48
49         if (!intf->ops || !intf->ops->blank)
50                 return -EOPNOTSUPP;
51
52         if (state > DRM_MODE_DPMS_OFF)
53                 return -EINVAL;
54
55         mutex_lock(&dev->client_lock);
56         if (state != DRM_MODE_DPMS_ON)
57                 flush_kthread_worker(&dev->post_worker);
58         mutex_lock(&intf->base.event_lock);
59
60         vsync_refcount = adf_obj_find_event_refcount(&intf->base,
61                         ADF_EVENT_VSYNC);
62         if (!vsync_refcount) {
63                 ret = -ENOMEM;
64                 goto done;
65         }
66
67         prev_state = intf->dpms_state;
68         if (prev_state == state) {
69                 ret = -EBUSY;
70                 goto done;
71         }
72
73         disable_vsync = vsync_active(prev_state) &&
74                         !vsync_active(state) &&
75                         vsync_refcount->refcount;
76         enable_vsync = !vsync_active(prev_state) &&
77                         vsync_active(state) &&
78                         vsync_refcount->refcount;
79
80         if (disable_vsync)
81                 intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
82                                 false);
83
84         ret = intf->ops->blank(intf, state);
85         if (ret < 0) {
86                 if (disable_vsync)
87                         intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
88                                         true);
89                 goto done;
90         }
91
92         if (enable_vsync)
93                 intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
94                                 true);
95
96         intf->dpms_state = state;
97 done:
98         mutex_unlock(&intf->base.event_lock);
99         mutex_unlock(&dev->client_lock);
100         return ret;
101 }
102 EXPORT_SYMBOL(adf_interface_blank);
103
104 /**
105  * adf_interface_blank - get interface's current DPMS state
106  *
107  * @intf: the interface
108  *
109  * Returns one of %DRM_MODE_DPMS_*.
110  */
111 u8 adf_interface_dpms_state(struct adf_interface *intf)
112 {
113         struct adf_device *dev = adf_interface_parent(intf);
114         u8 dpms_state;
115
116         mutex_lock(&dev->client_lock);
117         dpms_state = intf->dpms_state;
118         mutex_unlock(&dev->client_lock);
119
120         return dpms_state;
121 }
122 EXPORT_SYMBOL(adf_interface_dpms_state);
123
124 /**
125  * adf_interface_current_mode - get interface's current display mode
126  *
127  * @intf: the interface
128  * @mode: returns the current mode
129  */
130 void adf_interface_current_mode(struct adf_interface *intf,
131                 struct drm_mode_modeinfo *mode)
132 {
133         struct adf_device *dev = adf_interface_parent(intf);
134
135         mutex_lock(&dev->client_lock);
136         memcpy(mode, &intf->current_mode, sizeof(*mode));
137         mutex_unlock(&dev->client_lock);
138 }
139 EXPORT_SYMBOL(adf_interface_current_mode);
140
141 /**
142  * adf_interface_modelist - get interface's modelist
143  *
144  * @intf: the interface
145  * @modelist: storage for the modelist (optional)
146  * @n_modes: length of @modelist
147  *
148  * If @modelist is not NULL, adf_interface_modelist() will copy up to @n_modes
149  * modelist entries into @modelist.
150  *
151  * Returns the length of the modelist.
152  */
153 size_t adf_interface_modelist(struct adf_interface *intf,
154                 struct drm_mode_modeinfo *modelist, size_t n_modes)
155 {
156         unsigned long flags;
157         size_t retval;
158
159         read_lock_irqsave(&intf->hotplug_modelist_lock, flags);
160         if (modelist)
161                 memcpy(modelist, intf->modelist, sizeof(modelist[0]) *
162                                 min(n_modes, intf->n_modes));
163         retval = intf->n_modes;
164         read_unlock_irqrestore(&intf->hotplug_modelist_lock, flags);
165
166         return retval;
167 }
168 EXPORT_SYMBOL(adf_interface_modelist);
169
170 /**
171  * adf_interface_set_mode - set interface's display mode
172  *
173  * @intf: the interface
174  * @mode: the new mode
175  *
176  * Returns 0 on success or -errno on failure.
177  */
178 int adf_interface_set_mode(struct adf_interface *intf,
179                 struct drm_mode_modeinfo *mode)
180 {
181         struct adf_device *dev = adf_interface_parent(intf);
182         int ret = 0;
183
184         if (!intf->ops || !intf->ops->modeset)
185                 return -EOPNOTSUPP;
186
187         mutex_lock(&dev->client_lock);
188         flush_kthread_worker(&dev->post_worker);
189
190         ret = intf->ops->modeset(intf, mode);
191         if (ret < 0)
192                 goto done;
193
194         memcpy(&intf->current_mode, mode, sizeof(*mode));
195 done:
196         mutex_unlock(&dev->client_lock);
197         return ret;
198 }
199 EXPORT_SYMBOL(adf_interface_set_mode);
200
201 /**
202  * adf_interface_screen_size - get size of screen connected to interface
203  *
204  * @intf: the interface
205  * @width_mm: returns the screen width in mm
206  * @height_mm: returns the screen width in mm
207  *
208  * Returns 0 on success or -errno on failure.
209  */
210 int adf_interface_get_screen_size(struct adf_interface *intf, u16 *width_mm,
211                 u16 *height_mm)
212 {
213         struct adf_device *dev = adf_interface_parent(intf);
214         int ret;
215
216         if (!intf->ops || !intf->ops->screen_size)
217                 return -EOPNOTSUPP;
218
219         mutex_lock(&dev->client_lock);
220         ret = intf->ops->screen_size(intf, width_mm, height_mm);
221         mutex_unlock(&dev->client_lock);
222
223         return ret;
224 }
225 EXPORT_SYMBOL(adf_interface_get_screen_size);
226
227 /**
228  * adf_overlay_engine_supports_format - returns whether a format is in an
229  * overlay engine's supported list
230  *
231  * @eng: the overlay engine
232  * @format: format fourcc
233  */
234 bool adf_overlay_engine_supports_format(struct adf_overlay_engine *eng,
235                 u32 format)
236 {
237         size_t i;
238         for (i = 0; i < eng->ops->n_supported_formats; i++)
239                 if (format == eng->ops->supported_formats[i])
240                         return true;
241
242         return false;
243 }
244 EXPORT_SYMBOL(adf_overlay_engine_supports_format);
245
246 static int adf_buffer_validate(struct adf_buffer *buf)
247 {
248         struct adf_overlay_engine *eng = buf->overlay_engine;
249         struct device *dev = &eng->base.dev;
250         struct adf_device *parent = adf_overlay_engine_parent(eng);
251         u8 hsub, vsub, num_planes, cpp[ADF_MAX_PLANES], i;
252
253         if (!adf_overlay_engine_supports_format(eng, buf->format)) {
254                 char format_str[ADF_FORMAT_STR_SIZE];
255                 adf_format_str(buf->format, format_str);
256                 dev_err(dev, "unsupported format %s\n", format_str);
257                 return -EINVAL;
258         }
259
260         if (!adf_format_is_standard(buf->format))
261                 return parent->ops->validate_custom_format(parent, buf);
262
263         hsub = adf_format_horz_chroma_subsampling(buf->format);
264         vsub = adf_format_vert_chroma_subsampling(buf->format);
265         num_planes = adf_format_num_planes(buf->format);
266         for (i = 0; i < num_planes; i++)
267                 cpp[i] = adf_format_plane_cpp(buf->format, i);
268
269         return adf_format_validate_yuv(parent, buf, num_planes, hsub, vsub,
270                         cpp);
271 }
272
273 static int adf_buffer_map(struct adf_device *dev, struct adf_buffer *buf,
274                 struct adf_buffer_mapping *mapping)
275 {
276         int ret = 0;
277         size_t i;
278
279         for (i = 0; i < buf->n_planes; i++) {
280                 struct dma_buf_attachment *attachment;
281                 struct sg_table *sg_table;
282
283                 attachment = dma_buf_attach(buf->dma_bufs[i], dev->dev);
284                 if (IS_ERR(attachment)) {
285                         ret = PTR_ERR(attachment);
286                         dev_err(&dev->base.dev, "attaching plane %u failed: %d\n",
287                                         i, ret);
288                         goto done;
289                 }
290                 mapping->attachments[i] = attachment;
291
292                 sg_table = dma_buf_map_attachment(attachment, DMA_TO_DEVICE);
293                 if (IS_ERR(sg_table)) {
294                         ret = PTR_ERR(sg_table);
295                         dev_err(&dev->base.dev, "mapping plane %u failed: %d",
296                                         i, ret);
297                         goto done;
298                 } else if (!sg_table) {
299                         ret = -ENOMEM;
300                         dev_err(&dev->base.dev, "mapping plane %u failed\n", i);
301                         goto done;
302                 }
303                 mapping->sg_tables[i] = sg_table;
304         }
305
306 done:
307         if (ret < 0)
308                 adf_buffer_mapping_cleanup(mapping, buf);
309
310         return ret;
311 }
312
313 static struct sync_fence *adf_sw_complete_fence(struct adf_device *dev)
314 {
315         struct sync_pt *pt;
316         struct sync_fence *complete_fence;
317
318         if (!dev->timeline) {
319                 dev->timeline = sw_sync_timeline_create(dev->base.name);
320                 if (!dev->timeline)
321                         return ERR_PTR(-ENOMEM);
322                 dev->timeline_max = 1;
323         }
324
325         dev->timeline_max++;
326         pt = sw_sync_pt_create(dev->timeline, dev->timeline_max);
327         if (!pt)
328                 goto err_pt_create;
329         complete_fence = sync_fence_create(dev->base.name, pt);
330         if (!complete_fence)
331                 goto err_fence_create;
332
333         return complete_fence;
334
335 err_fence_create:
336         sync_pt_free(pt);
337 err_pt_create:
338         dev->timeline_max--;
339         return ERR_PTR(-ENOSYS);
340 }
341
342 /**
343  * adf_device_post - flip to a new set of buffers
344  *
345  * @dev: device targeted by the flip
346  * @intfs: interfaces targeted by the flip
347  * @n_intfs: number of targeted interfaces
348  * @bufs: description of buffers displayed
349  * @n_bufs: number of buffers displayed
350  * @custom_data: driver-private data
351  * @custom_data_size: size of driver-private data
352  *
353  * adf_device_post() will copy @intfs, @bufs, and @custom_data, so they may
354  * point to variables on the stack.  adf_device_post() also takes its own
355  * reference on each of the dma-bufs in @bufs.  The adf_device_post_nocopy()
356  * variant transfers ownership of these resources to ADF instead.
357  *
358  * On success, returns a sync fence which signals when the buffers are removed
359  * from the screen.  On failure, returns ERR_PTR(-errno).
360  */
361 struct sync_fence *adf_device_post(struct adf_device *dev,
362                 struct adf_interface **intfs, size_t n_intfs,
363                 struct adf_buffer *bufs, size_t n_bufs, void *custom_data,
364                 size_t custom_data_size)
365 {
366         struct adf_interface **intfs_copy = NULL;
367         struct adf_buffer *bufs_copy = NULL;
368         void *custom_data_copy = NULL;
369         struct sync_fence *ret;
370         size_t i;
371
372         intfs_copy = kzalloc(sizeof(intfs_copy[0]) * n_intfs, GFP_KERNEL);
373         if (!intfs_copy)
374                 return ERR_PTR(-ENOMEM);
375
376         bufs_copy = kzalloc(sizeof(bufs_copy[0]) * n_bufs, GFP_KERNEL);
377         if (!bufs_copy) {
378                 ret = ERR_PTR(-ENOMEM);
379                 goto err_alloc;
380         }
381
382         custom_data_copy = kzalloc(custom_data_size, GFP_KERNEL);
383         if (!custom_data_copy) {
384                 ret = ERR_PTR(-ENOMEM);
385                 goto err_alloc;
386         }
387
388         for (i = 0; i < n_bufs; i++) {
389                 size_t j;
390                 for (j = 0; j < bufs[i].n_planes; j++)
391                         get_dma_buf(bufs[i].dma_bufs[j]);
392         }
393
394         memcpy(intfs_copy, intfs, sizeof(intfs_copy[0]) * n_intfs);
395         memcpy(bufs_copy, bufs, sizeof(bufs_copy[0]) * n_bufs);
396         memcpy(custom_data_copy, custom_data, custom_data_size);
397
398         ret = adf_device_post_nocopy(dev, intfs_copy, n_intfs, bufs_copy,
399                         n_bufs, custom_data_copy, custom_data_size);
400         if (IS_ERR(ret))
401                 goto err_post;
402
403         return ret;
404
405 err_post:
406         for (i = 0; i < n_bufs; i++) {
407                 size_t j;
408                 for (j = 0; j < bufs[i].n_planes; j++)
409                         dma_buf_put(bufs[i].dma_bufs[j]);
410         }
411 err_alloc:
412         kfree(custom_data_copy);
413         kfree(bufs_copy);
414         kfree(intfs_copy);
415         return ret;
416 }
417 EXPORT_SYMBOL(adf_device_post);
418
419 /**
420  * adf_device_post_nocopy - flip to a new set of buffers
421  *
422  * adf_device_post_nocopy() has the same behavior as adf_device_post(),
423  * except ADF does not copy @intfs, @bufs, or @custom_data, and it does
424  * not take an extra reference on the dma-bufs in @bufs.
425  *
426  * @intfs, @bufs, and @custom_data must point to buffers allocated by
427  * kmalloc().  On success, ADF takes ownership of these buffers and the dma-bufs
428  * in @bufs, and will kfree()/dma_buf_put() them when they are no longer needed.
429  * On failure, adf_device_post_nocopy() does NOT take ownership of these
430  * buffers or the dma-bufs, and the caller must clean them up.
431  *
432  * adf_device_post_nocopy() is mainly intended for implementing ADF's ioctls.
433  * Clients may find the nocopy variant useful in limited cases, but most should
434  * call adf_device_post() instead.
435  */
436 struct sync_fence *adf_device_post_nocopy(struct adf_device *dev,
437                 struct adf_interface **intfs, size_t n_intfs,
438                 struct adf_buffer *bufs, size_t n_bufs,
439                 void *custom_data, size_t custom_data_size)
440 {
441         struct adf_pending_post *cfg;
442         struct adf_buffer_mapping *mappings;
443         struct sync_fence *ret;
444         size_t i;
445         int err;
446
447         cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
448         if (!cfg)
449                 return ERR_PTR(-ENOMEM);
450
451         mappings = kzalloc(sizeof(mappings[0]) * n_bufs, GFP_KERNEL);
452         if (!mappings) {
453                 ret = ERR_PTR(-ENOMEM);
454                 goto err_alloc;
455         }
456
457         mutex_lock(&dev->client_lock);
458
459         for (i = 0; i < n_bufs; i++) {
460                 err = adf_buffer_validate(&bufs[i]);
461                 if (err < 0) {
462                         ret = ERR_PTR(err);
463                         goto err_buf;
464                 }
465
466                 err = adf_buffer_map(dev, &bufs[i], &mappings[i]);
467                 if (err < 0) {
468                         ret = ERR_PTR(err);
469                         goto err_buf;
470                 }
471         }
472
473         INIT_LIST_HEAD(&cfg->head);
474         cfg->config.n_bufs = n_bufs;
475         cfg->config.bufs = bufs;
476         cfg->config.mappings = mappings;
477         cfg->config.custom_data = custom_data;
478         cfg->config.custom_data_size = custom_data_size;
479
480         err = dev->ops->validate(dev, &cfg->config, &cfg->state);
481         if (err < 0) {
482                 ret = ERR_PTR(err);
483                 goto err_buf;
484         }
485
486         mutex_lock(&dev->post_lock);
487
488         if (dev->ops->complete_fence)
489                 ret = dev->ops->complete_fence(dev, &cfg->config,
490                                 cfg->state);
491         else
492                 ret = adf_sw_complete_fence(dev);
493
494         if (IS_ERR(ret))
495                 goto err_fence;
496
497         list_add_tail(&cfg->head, &dev->post_list);
498         queue_kthread_work(&dev->post_worker, &dev->post_work);
499         mutex_unlock(&dev->post_lock);
500         mutex_unlock(&dev->client_lock);
501         kfree(intfs);
502         return ret;
503
504 err_fence:
505         mutex_unlock(&dev->post_lock);
506
507 err_buf:
508         for (i = 0; i < n_bufs; i++)
509                 adf_buffer_mapping_cleanup(&mappings[i], &bufs[i]);
510
511         mutex_unlock(&dev->client_lock);
512         kfree(mappings);
513
514 err_alloc:
515         kfree(cfg);
516         return ret;
517 }
518 EXPORT_SYMBOL(adf_device_post_nocopy);
519
520 static void adf_attachment_list_to_array(struct adf_device *dev,
521                 struct list_head *src, struct adf_attachment *dst, size_t size)
522 {
523         struct adf_attachment_list *entry;
524         size_t i = 0;
525
526         if (!dst)
527                 return;
528
529         list_for_each_entry(entry, src, head) {
530                 if (i == size)
531                         return;
532                 dst[i] = entry->attachment;
533                 i++;
534         }
535 }
536
537 /**
538  * adf_device_attachments - get device's list of active attachments
539  *
540  * @dev: the device
541  * @attachments: storage for the attachment list (optional)
542  * @n_attachments: length of @attachments
543  *
544  * If @attachments is not NULL, adf_device_attachments() will copy up to
545  * @n_attachments entries into @attachments.
546  *
547  * Returns the length of the active attachment list.
548  */
549 size_t adf_device_attachments(struct adf_device *dev,
550                 struct adf_attachment *attachments, size_t n_attachments)
551 {
552         size_t retval;
553
554         mutex_lock(&dev->client_lock);
555         adf_attachment_list_to_array(dev, &dev->attached, attachments,
556                         n_attachments);
557         retval = dev->n_attached;
558         mutex_unlock(&dev->client_lock);
559
560         return retval;
561 }
562 EXPORT_SYMBOL(adf_device_attachments);
563
564 /**
565  * adf_device_attachments_allowed - get device's list of allowed attachments
566  *
567  * @dev: the device
568  * @attachments: storage for the attachment list (optional)
569  * @n_attachments: length of @attachments
570  *
571  * If @attachments is not NULL, adf_device_attachments_allowed() will copy up to
572  * @n_attachments entries into @attachments.
573  *
574  * Returns the length of the allowed attachment list.
575  */
576 size_t adf_device_attachments_allowed(struct adf_device *dev,
577                 struct adf_attachment *attachments, size_t n_attachments)
578 {
579         size_t retval;
580
581         mutex_lock(&dev->client_lock);
582         adf_attachment_list_to_array(dev, &dev->attach_allowed, attachments,
583                         n_attachments);
584         retval = dev->n_attach_allowed;
585         mutex_unlock(&dev->client_lock);
586
587         return retval;
588 }
589 EXPORT_SYMBOL(adf_device_attachments_allowed);
590
591 /**
592  * adf_device_attached - return whether an overlay engine and interface are
593  * attached
594  *
595  * @dev: the parent device
596  * @eng: the overlay engine
597  * @intf: the interface
598  */
599 bool adf_device_attached(struct adf_device *dev, struct adf_overlay_engine *eng,
600                 struct adf_interface *intf)
601 {
602         struct adf_attachment_list *attachment;
603
604         mutex_lock(&dev->client_lock);
605         attachment = adf_attachment_find(&dev->attached, eng, intf);
606         mutex_unlock(&dev->client_lock);
607
608         return attachment != NULL;
609 }
610 EXPORT_SYMBOL(adf_device_attached);
611
612 /**
613  * adf_device_attach_allowed - return whether the ADF device supports attaching
614  * an overlay engine and interface
615  *
616  * @dev: the parent device
617  * @eng: the overlay engine
618  * @intf: the interface
619  */
620 bool adf_device_attach_allowed(struct adf_device *dev,
621                 struct adf_overlay_engine *eng, struct adf_interface *intf)
622 {
623         struct adf_attachment_list *attachment;
624
625         mutex_lock(&dev->client_lock);
626         attachment = adf_attachment_find(&dev->attach_allowed, eng, intf);
627         mutex_unlock(&dev->client_lock);
628
629         return attachment != NULL;
630 }
631 EXPORT_SYMBOL(adf_device_attach_allowed);
632 /**
633  * adf_device_attach - attach an overlay engine to an interface
634  *
635  * @dev: the parent device
636  * @eng: the overlay engine
637  * @intf: the interface
638  *
639  * Returns 0 on success, -%EINVAL if attaching @intf and @eng is not allowed,
640  * -%EALREADY if @intf and @eng are already attached, or -errno on any other
641  * failure.
642  */
643 int adf_device_attach(struct adf_device *dev, struct adf_overlay_engine *eng,
644                 struct adf_interface *intf)
645 {
646         int ret;
647         struct adf_attachment_list *attachment = NULL;
648
649         ret = adf_attachment_validate(dev, eng, intf);
650         if (ret < 0)
651                 return ret;
652
653         mutex_lock(&dev->client_lock);
654
655         if (dev->n_attached == ADF_MAX_ATTACHMENTS) {
656                 ret = -ENOMEM;
657                 goto done;
658         }
659
660         if (!adf_attachment_find(&dev->attach_allowed, eng, intf)) {
661                 ret = -EINVAL;
662                 goto done;
663         }
664
665         if (adf_attachment_find(&dev->attached, eng, intf)) {
666                 ret = -EALREADY;
667                 goto done;
668         }
669
670         ret = adf_device_attach_op(dev, eng, intf);
671         if (ret < 0)
672                 goto done;
673
674         attachment = kzalloc(sizeof(*attachment), GFP_KERNEL);
675         if (!attachment) {
676                 ret = -ENOMEM;
677                 goto done;
678         }
679
680         attachment->attachment.interface = intf;
681         attachment->attachment.overlay_engine = eng;
682         list_add_tail(&attachment->head, &dev->attached);
683         dev->n_attached++;
684
685 done:
686         mutex_unlock(&dev->client_lock);
687         if (ret < 0)
688                 kfree(attachment);
689
690         return ret;
691 }
692 EXPORT_SYMBOL(adf_device_attach);
693
694 /**
695  * adf_device_detach - detach an overlay engine from an interface
696  *
697  * @dev: the parent device
698  * @eng: the overlay engine
699  * @intf: the interface
700  *
701  * Returns 0 on success, -%EINVAL if @intf and @eng are not attached,
702  * or -errno on any other failure.
703  */
704 int adf_device_detach(struct adf_device *dev, struct adf_overlay_engine *eng,
705                 struct adf_interface *intf)
706 {
707         int ret;
708         struct adf_attachment_list *attachment;
709
710         ret = adf_attachment_validate(dev, eng, intf);
711         if (ret < 0)
712                 return ret;
713
714         mutex_lock(&dev->client_lock);
715
716         attachment = adf_attachment_find(&dev->attached, eng, intf);
717         if (!attachment) {
718                 ret = -EINVAL;
719                 goto done;
720         }
721
722         ret = adf_device_detach_op(dev, eng, intf);
723         if (ret < 0)
724                 goto done;
725
726         adf_attachment_free(attachment);
727         dev->n_attached--;
728 done:
729         mutex_unlock(&dev->client_lock);
730         return ret;
731 }
732 EXPORT_SYMBOL(adf_device_detach);
733
734 /**
735  * adf_interface_simple_buffer_alloc - allocate a simple buffer
736  *
737  * @intf: target interface
738  * @w: width in pixels
739  * @h: height in pixels
740  * @format: format fourcc
741  * @dma_buf: returns the allocated buffer
742  * @offset: returns the byte offset of the allocated buffer's first pixel
743  * @pitch: returns the allocated buffer's pitch
744  *
745  * See &struct adf_simple_buffer_alloc for a description of simple buffers and
746  * their limitations.
747  *
748  * Returns 0 on success or -errno on failure.
749  */
750 int adf_interface_simple_buffer_alloc(struct adf_interface *intf, u16 w, u16 h,
751                 u32 format, struct dma_buf **dma_buf, u32 *offset, u32 *pitch)
752 {
753         if (!intf->ops || !intf->ops->alloc_simple_buffer)
754                 return -EOPNOTSUPP;
755
756         if (!adf_format_is_rgb(format))
757                 return -EINVAL;
758
759         return intf->ops->alloc_simple_buffer(intf, w, h, format, dma_buf,
760                         offset, pitch);
761 }
762 EXPORT_SYMBOL(adf_interface_simple_buffer_alloc);
763
764 /**
765  * adf_interface_simple_post - flip to a single buffer
766  *
767  * @intf: interface targeted by the flip
768  * @buf: buffer to display
769  *
770  * adf_interface_simple_post() can be used generically for simple display
771  * configurations, since the client does not need to provide any driver-private
772  * configuration data.
773  *
774  * adf_interface_simple_post() has the same copying semantics as
775  * adf_device_post().
776  *
777  * On success, returns a sync fence which signals when the buffer is removed
778  * from the screen.  On failure, returns ERR_PTR(-errno).
779  */
780 struct sync_fence *adf_interface_simple_post(struct adf_interface *intf,
781                 struct adf_buffer *buf)
782 {
783         size_t custom_data_size = 0;
784         void *custom_data = NULL;
785         struct sync_fence *ret;
786
787         if (intf->ops && intf->ops->describe_simple_post) {
788                 int err;
789
790                 custom_data = kzalloc(ADF_MAX_CUSTOM_DATA_SIZE, GFP_KERNEL);
791                 if (!custom_data) {
792                         ret = ERR_PTR(-ENOMEM);
793                         goto done;
794                 }
795
796                 err = intf->ops->describe_simple_post(intf, buf, custom_data,
797                                 &custom_data_size);
798                 if (err < 0) {
799                         ret = ERR_PTR(err);
800                         goto done;
801                 }
802         }
803
804         ret = adf_device_post(adf_interface_parent(intf), &intf, 1, buf, 1,
805                         custom_data, custom_data_size);
806 done:
807         kfree(custom_data);
808         return ret;
809 }
810 EXPORT_SYMBOL(adf_interface_simple_post);