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