• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <dirent.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include <linux/limits.h>
25 
26 #include <sys/ioctl.h>
27 
28 #include <adf/adf.h>
29 
30 #define ADF_BASE_PATH "/dev/"
31 
adf_find_nodes(const char * pattern,adf_id_t ** ids)32 static ssize_t adf_find_nodes(const char *pattern, adf_id_t **ids)
33 {
34     DIR *dir;
35     struct dirent *dirent;
36     size_t n = 0;
37     ssize_t ret;
38     adf_id_t *ids_ret = NULL;
39 
40     dir = opendir(ADF_BASE_PATH);
41     if (!dir)
42         return -errno;
43 
44     errno = 0;
45     while ((dirent = readdir(dir))) {
46         adf_id_t id;
47         int matched = sscanf(dirent->d_name, pattern, &id);
48 
49         if (matched < 0) {
50             ret = -errno;
51             goto done;
52         } else if (matched != 1) {
53             continue;
54         }
55 
56         adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
57         if (!new_ids) {
58             ret = -ENOMEM;
59             goto done;
60         }
61 
62         ids_ret = new_ids;
63         ids_ret[n] = id;
64         n++;
65     }
66     if (errno)
67         ret = -errno;
68     else
69         ret = n;
70 
71 done:
72     closedir(dir);
73     if (ret < 0)
74         free(ids_ret);
75     else
76         *ids = ids_ret;
77     return ret;
78 }
79 
adf_devices(adf_id_t ** ids)80 ssize_t adf_devices(adf_id_t **ids)
81 {
82     return adf_find_nodes("adf%u", ids);
83 }
84 
adf_device_open(adf_id_t id,int flags,struct adf_device * dev)85 int adf_device_open(adf_id_t id, int flags, struct adf_device *dev)
86 {
87     char filename[64];
88     int err;
89 
90     dev->id = id;
91 
92     snprintf(filename, sizeof(filename), ADF_BASE_PATH "adf%u", id);
93     dev->fd = open(filename, flags);
94     if (dev->fd < 0)
95         return -errno;
96 
97     return 0;
98 }
99 
adf_device_close(struct adf_device * dev)100 void adf_device_close(struct adf_device *dev)
101 {
102     if (dev->fd >= 0)
103         close(dev->fd);
104 }
105 
adf_get_device_data(struct adf_device * dev,struct adf_device_data * data)106 int adf_get_device_data(struct adf_device *dev, struct adf_device_data *data)
107 {
108     int err;
109     int ret = 0;
110 
111     memset(data, 0, sizeof(*data));
112 
113     err = ioctl(dev->fd, ADF_GET_DEVICE_DATA, data);
114     if (err < 0)
115         return -ENOMEM;
116 
117     if (data->n_attachments) {
118         data->attachments = malloc(sizeof(data->attachments[0]) *
119                 data->n_attachments);
120         if (!data->attachments)
121             return -ENOMEM;
122     }
123 
124     if (data->n_allowed_attachments) {
125         data->allowed_attachments =
126                 malloc(sizeof(data->allowed_attachments[0]) *
127                         data->n_allowed_attachments);
128         if (!data->allowed_attachments) {
129             ret = -ENOMEM;
130             goto done;
131         }
132     }
133 
134     if (data->custom_data_size) {
135         data->custom_data = malloc(data->custom_data_size);
136         if (!data->custom_data) {
137             ret = -ENOMEM;
138             goto done;
139         }
140     }
141 
142     err = ioctl(dev->fd, ADF_GET_DEVICE_DATA, data);
143     if (err < 0)
144         ret = -errno;
145 
146 done:
147     if (ret < 0)
148         adf_free_device_data(data);
149     return ret;
150 }
151 
adf_free_device_data(struct adf_device_data * data)152 void adf_free_device_data(struct adf_device_data *data)
153 {
154     free(data->attachments);
155     free(data->allowed_attachments);
156     free(data->custom_data);
157 }
158 
adf_device_post(struct adf_device * dev,adf_id_t * interfaces,size_t n_interfaces,struct adf_buffer_config * bufs,size_t n_bufs,void * custom_data,size_t custom_data_size)159 int adf_device_post(struct adf_device *dev,
160         adf_id_t *interfaces, size_t n_interfaces,
161         struct adf_buffer_config *bufs, size_t n_bufs,
162         void *custom_data, size_t custom_data_size)
163 {
164     int err;
165     struct adf_post_config data;
166 
167     memset(&data, 0, sizeof(data));
168     data.interfaces = interfaces;
169     data.n_interfaces = n_interfaces;
170     data.bufs = bufs;
171     data.n_bufs = n_bufs;
172     data.custom_data = custom_data;
173     data.custom_data_size = custom_data_size;
174 
175     err = ioctl(dev->fd, ADF_POST_CONFIG, &data);
176     if (err < 0)
177         return -errno;
178 
179     return (int)data.complete_fence;
180 }
181 
adf_device_attachment(struct adf_device * dev,adf_id_t overlay_engine,adf_id_t interface,bool attach)182 static int adf_device_attachment(struct adf_device *dev,
183         adf_id_t overlay_engine, adf_id_t interface, bool attach)
184 {
185     int err;
186     struct adf_attachment_config data;
187 
188     memset(&data, 0, sizeof(data));
189     data.overlay_engine = overlay_engine;
190     data.interface = interface;
191 
192     err = ioctl(dev->fd, attach ? ADF_ATTACH : ADF_DETACH, &data);
193     if (err < 0)
194         return -errno;
195 
196     return 0;
197 }
198 
adf_device_attach(struct adf_device * dev,adf_id_t overlay_engine,adf_id_t interface)199 int adf_device_attach(struct adf_device *dev, adf_id_t overlay_engine,
200                       adf_id_t interface)
201 {
202    return adf_device_attachment(dev, overlay_engine, interface, true);
203 }
204 
adf_device_detach(struct adf_device * dev,adf_id_t overlay_engine,adf_id_t interface)205 int adf_device_detach(struct adf_device *dev, adf_id_t overlay_engine,
206                       adf_id_t interface)
207 {
208    return adf_device_attachment(dev, overlay_engine, interface, false);
209 }
210 
adf_interfaces(struct adf_device * dev,adf_id_t ** interfaces)211 ssize_t adf_interfaces(struct adf_device *dev, adf_id_t **interfaces)
212 {
213     char pattern[64];
214 
215     snprintf(pattern, sizeof(pattern), "adf-interface%u.%%u", dev->id);
216     return adf_find_nodes(pattern, interfaces);
217 }
218 
adf_interfaces_for_overlay_engine(struct adf_device * dev,adf_id_t overlay_engine,adf_id_t ** interfaces)219 ssize_t adf_interfaces_for_overlay_engine(struct adf_device *dev,
220         adf_id_t overlay_engine, adf_id_t **interfaces)
221 {
222     struct adf_device_data data;
223     ssize_t n = 0;
224     ssize_t ret;
225     adf_id_t *ids_ret = NULL;
226 
227     ret = adf_get_device_data(dev, &data);
228     if (ret < 0)
229         return ret;
230 
231     size_t i;
232     for (i = 0; i < data.n_allowed_attachments; i++) {
233         if (data.allowed_attachments[i].overlay_engine != overlay_engine)
234             continue;
235 
236         adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
237         if (!new_ids) {
238             ret = -ENOMEM;
239             goto done;
240         }
241 
242         ids_ret = new_ids;
243         ids_ret[n] = data.allowed_attachments[i].interface;
244         n++;
245     }
246 
247     ret = n;
248 
249 done:
250     adf_free_device_data(&data);
251     if (ret < 0)
252         free(ids_ret);
253     else
254         *interfaces = ids_ret;
255     return ret;
256 }
257 
adf_interfaces_filter(struct adf_device * dev,adf_id_t * in,size_t n_in,adf_id_t ** out,bool (* filter)(struct adf_interface_data * data,__u32 match),__u32 match)258 static ssize_t adf_interfaces_filter(struct adf_device *dev,
259         adf_id_t *in, size_t n_in, adf_id_t **out,
260         bool (*filter)(struct adf_interface_data *data, __u32 match),
261         __u32 match)
262 {
263     size_t n = 0;
264     ssize_t ret;
265     adf_id_t *ids_ret = NULL;
266 
267     size_t i;
268     for (i = 0; i < n_in; i++) {
269         int fd = adf_interface_open(dev, in[i], O_RDONLY);
270         if (fd < 0) {
271             ret = fd;
272             goto done;
273         }
274 
275         struct adf_interface_data data;
276         ret = adf_get_interface_data(fd, &data);
277         close(fd);
278         if (ret < 0)
279             goto done;
280 
281         if (!filter(&data, match))
282             continue;
283 
284         adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
285         if (!new_ids) {
286             ret = -ENOMEM;
287             goto done;
288         }
289 
290         ids_ret = new_ids;
291         ids_ret[n] = in[i];
292         n++;
293     }
294 
295     ret = n;
296 
297 done:
298     if (ret < 0)
299         free(ids_ret);
300     else
301         *out = ids_ret;
302     return ret;
303 }
304 
adf_interface_type_filter(struct adf_interface_data * data,__u32 type)305 static bool adf_interface_type_filter(struct adf_interface_data *data,
306         __u32 type)
307 {
308     return data->type == (enum adf_interface_type)type;
309 }
310 
adf_interfaces_filter_by_type(struct adf_device * dev,enum adf_interface_type type,adf_id_t * in,size_t n_in,adf_id_t ** out)311 ssize_t adf_interfaces_filter_by_type(struct adf_device *dev,
312         enum adf_interface_type type,
313         adf_id_t *in, size_t n_in, adf_id_t **out)
314 {
315     return adf_interfaces_filter(dev, in, n_in, out, adf_interface_type_filter,
316             type);
317 }
318 
adf_interface_flags_filter(struct adf_interface_data * data,__u32 flag)319 static bool adf_interface_flags_filter(struct adf_interface_data *data,
320         __u32 flag)
321 {
322     return !!(data->flags & flag);
323 }
324 
adf_interfaces_filter_by_flag(struct adf_device * dev,__u32 flag,adf_id_t * in,size_t n_in,adf_id_t ** out)325 ssize_t adf_interfaces_filter_by_flag(struct adf_device *dev, __u32 flag,
326         adf_id_t *in, size_t n_in, adf_id_t **out)
327 {
328     return adf_interfaces_filter(dev, in, n_in, out, adf_interface_flags_filter,
329             flag);
330 }
331 
adf_interface_open(struct adf_device * dev,adf_id_t id,int flags)332 int adf_interface_open(struct adf_device *dev, adf_id_t id, int flags)
333 {
334     char filename[64];
335 
336     snprintf(filename, sizeof(filename), ADF_BASE_PATH "adf-interface%u.%u",
337             dev->id, id);
338 
339     int fd = open(filename, flags);
340     if (fd < 0)
341         return -errno;
342     return fd;
343 }
344 
adf_get_interface_data(int fd,struct adf_interface_data * data)345 int adf_get_interface_data(int fd, struct adf_interface_data *data)
346 {
347     int err;
348     int ret = 0;
349 
350     memset(data, 0, sizeof(*data));
351 
352     err = ioctl(fd, ADF_GET_INTERFACE_DATA, data);
353     if (err < 0)
354         return -errno;
355 
356     if (data->n_available_modes) {
357         data->available_modes = malloc(sizeof(data->available_modes[0]) *
358                 data->n_available_modes);
359         if (!data->available_modes)
360             return -ENOMEM;
361     }
362 
363     if (data->custom_data_size) {
364         data->custom_data = malloc(data->custom_data_size);
365         if (!data->custom_data) {
366             ret = -ENOMEM;
367             goto done;
368         }
369     }
370 
371     err = ioctl(fd, ADF_GET_INTERFACE_DATA, data);
372     if (err < 0)
373         ret = -errno;
374 
375 done:
376     if (ret < 0)
377         adf_free_interface_data(data);
378     return ret;
379 }
380 
adf_free_interface_data(struct adf_interface_data * data)381 void adf_free_interface_data(struct adf_interface_data *data)
382 {
383     free(data->available_modes);
384     free(data->custom_data);
385 }
386 
adf_interface_blank(int fd,__u8 mode)387 int adf_interface_blank(int fd, __u8 mode)
388 {
389     int err = ioctl(fd, ADF_BLANK, mode);
390     if (err < 0)
391         return -errno;
392     return 0;
393 }
394 
adf_interface_set_mode(int fd,struct drm_mode_modeinfo * mode)395 int adf_interface_set_mode(int fd, struct drm_mode_modeinfo *mode)
396 {
397     int err = ioctl(fd, ADF_SET_MODE, mode);
398     if (err < 0)
399         return -errno;
400     return 0;
401 }
402 
adf_interface_simple_buffer_alloc(int fd,__u32 w,__u32 h,__u32 format,__u32 * offset,__u32 * pitch)403 int adf_interface_simple_buffer_alloc(int fd, __u32 w, __u32 h,
404         __u32 format, __u32 *offset, __u32 *pitch)
405 {
406     int err;
407     struct adf_simple_buffer_alloc data;
408 
409     memset(&data, 0, sizeof(data));
410     data.w = w;
411     data.h = h;
412     data.format = format;
413 
414     err = ioctl(fd, ADF_SIMPLE_BUFFER_ALLOC, &data);
415     if (err < 0)
416         return -errno;
417 
418     *offset = data.offset;
419     *pitch = data.pitch;
420     return (int)data.fd;
421 }
422 
adf_interface_simple_post(int fd,__u32 overlay_engine,__u32 w,__u32 h,__u32 format,int buf_fd,__u32 offset,__u32 pitch,int acquire_fence)423 int adf_interface_simple_post(int fd, __u32 overlay_engine,
424         __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset,
425         __u32 pitch, int acquire_fence)
426 {
427     int ret;
428     struct adf_simple_post_config data;
429 
430     memset(&data, 0, sizeof(data));
431     data.buf.overlay_engine = overlay_engine;
432     data.buf.w = w;
433     data.buf.h = h;
434     data.buf.format = format;
435     data.buf.fd[0] = buf_fd;
436     data.buf.offset[0] = offset;
437     data.buf.pitch[0] = pitch;
438     data.buf.n_planes = 1;
439     data.buf.acquire_fence = acquire_fence;
440 
441     ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG, &data);
442     if (ret < 0)
443         return -errno;
444 
445     return (int)data.complete_fence;
446 }
447 
adf_overlay_engines(struct adf_device * dev,adf_id_t ** overlay_engines)448 ssize_t adf_overlay_engines(struct adf_device *dev, adf_id_t **overlay_engines)
449 {
450     char pattern[64];
451 
452     snprintf(pattern, sizeof(pattern), "adf-overlay-engine%u.%%u", dev->id);
453     return adf_find_nodes(pattern, overlay_engines);
454 }
455 
adf_overlay_engines_for_interface(struct adf_device * dev,adf_id_t interface,adf_id_t ** overlay_engines)456 ssize_t adf_overlay_engines_for_interface(struct adf_device *dev,
457         adf_id_t interface, adf_id_t **overlay_engines)
458 {
459     struct adf_device_data data;
460     ssize_t n = 0;
461     ssize_t ret;
462     adf_id_t *ids_ret = NULL;
463 
464     ret = adf_get_device_data(dev, &data);
465     if (ret < 0)
466         return ret;
467 
468     size_t i;
469     for (i = 0; i < data.n_allowed_attachments; i++) {
470         if (data.allowed_attachments[i].interface != interface)
471             continue;
472 
473         adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
474         if (!new_ids) {
475             ret = -ENOMEM;
476             goto done;
477         }
478 
479         ids_ret = new_ids;
480         ids_ret[n] = data.allowed_attachments[i].overlay_engine;
481         n++;
482     }
483 
484     ret = n;
485 
486 done:
487     adf_free_device_data(&data);
488     if (ret < 0)
489         free(ids_ret);
490     else
491         *overlay_engines = ids_ret;
492     return ret;
493 }
494 
adf_overlay_engines_filter(struct adf_device * dev,adf_id_t * in,size_t n_in,adf_id_t ** out,bool (* filter)(struct adf_overlay_engine_data * data,void * cookie),void * cookie)495 static ssize_t adf_overlay_engines_filter(struct adf_device *dev,
496         adf_id_t *in, size_t n_in, adf_id_t **out,
497         bool (*filter)(struct adf_overlay_engine_data *data, void *cookie),
498         void *cookie)
499 {
500     size_t n = 0;
501     ssize_t ret;
502     adf_id_t *ids_ret = NULL;
503 
504     size_t i;
505     for (i = 0; i < n_in; i++) {
506         int fd = adf_overlay_engine_open(dev, in[i], O_RDONLY);
507         if (fd < 0) {
508             ret = fd;
509             goto done;
510         }
511 
512         struct adf_overlay_engine_data data;
513         ret = adf_get_overlay_engine_data(fd, &data);
514         close(fd);
515         if (ret < 0)
516             goto done;
517 
518         if (!filter(&data, cookie))
519             continue;
520 
521         adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
522         if (!new_ids) {
523             ret = -ENOMEM;
524             goto done;
525         }
526 
527         ids_ret = new_ids;
528         ids_ret[n] = in[i];
529         n++;
530     }
531 
532     ret = n;
533 
534 done:
535     if (ret < 0)
536         free(ids_ret);
537     else
538         *out = ids_ret;
539     return ret;
540 }
541 
542 struct format_filter_cookie {
543     const __u32 *formats;
544     size_t n_formats;
545 };
546 
adf_overlay_engine_format_filter(struct adf_overlay_engine_data * data,void * cookie)547 static bool adf_overlay_engine_format_filter(
548         struct adf_overlay_engine_data *data, void *cookie)
549 {
550     struct format_filter_cookie *c = cookie;
551     size_t i;
552     for (i = 0; i < data->n_supported_formats; i++) {
553         size_t j;
554         for (j = 0; j < c->n_formats; j++)
555             if (data->supported_formats[i] == c->formats[j])
556                 return true;
557     }
558     return false;
559 }
560 
adf_overlay_engines_filter_by_format(struct adf_device * dev,const __u32 * formats,size_t n_formats,adf_id_t * in,size_t n_in,adf_id_t ** out)561 ssize_t adf_overlay_engines_filter_by_format(struct adf_device *dev,
562         const __u32 *formats, size_t n_formats, adf_id_t *in, size_t n_in,
563         adf_id_t **out)
564 {
565     struct format_filter_cookie cookie = { formats, n_formats };
566     return adf_overlay_engines_filter(dev, in, n_in, out,
567             adf_overlay_engine_format_filter, &cookie);
568 }
569 
adf_overlay_engine_open(struct adf_device * dev,adf_id_t id,int flags)570 int adf_overlay_engine_open(struct adf_device *dev, adf_id_t id, int flags)
571 {
572     char filename[64];
573 
574     snprintf(filename, sizeof(filename),
575             ADF_BASE_PATH "adf-overlay-engine%u.%u", dev->id, id);
576 
577     int fd = open(filename, flags);
578     if (fd < 0)
579         return -errno;
580     return fd;
581 }
582 
adf_get_overlay_engine_data(int fd,struct adf_overlay_engine_data * data)583 int adf_get_overlay_engine_data(int fd, struct adf_overlay_engine_data *data)
584 {
585     int err;
586     int ret = 0;
587 
588     memset(data, 0, sizeof(*data));
589 
590     err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data);
591     if (err < 0)
592         return -errno;
593 
594     if (data->n_supported_formats) {
595         data->supported_formats = malloc(sizeof(data->supported_formats[0]) *
596               data->n_supported_formats);
597         if (!data->supported_formats)
598             return -ENOMEM;
599     }
600 
601     if (data->custom_data_size) {
602       data->custom_data = malloc(data->custom_data_size);
603       if (!data->custom_data) {
604           ret = -ENOMEM;
605           goto done;
606       }
607     }
608 
609     err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data);
610     if (err < 0)
611         ret = -errno;
612 
613 done:
614     if (ret < 0)
615         adf_free_overlay_engine_data(data);
616     return ret;
617 }
618 
adf_free_overlay_engine_data(struct adf_overlay_engine_data * data)619 void adf_free_overlay_engine_data(struct adf_overlay_engine_data *data)
620 {
621     free(data->supported_formats);
622     free(data->custom_data);
623 }
624 
adf_overlay_engine_supports_format(int fd,__u32 format)625 bool adf_overlay_engine_supports_format(int fd, __u32 format)
626 {
627     struct adf_overlay_engine_data data;
628     bool ret = false;
629     size_t i;
630 
631     int err = adf_get_overlay_engine_data(fd, &data);
632     if (err < 0)
633         return false;
634 
635     for (i = 0; i < data.n_supported_formats; i++) {
636         if (data.supported_formats[i] == format) {
637             ret = true;
638             break;
639         }
640     }
641 
642     adf_free_overlay_engine_data(&data);
643     return ret;
644 }
645 
adf_set_event(int fd,enum adf_event_type type,bool enabled)646 int adf_set_event(int fd, enum adf_event_type type, bool enabled)
647 {
648     struct adf_set_event data;
649 
650     data.type = type;
651     data.enabled = enabled;
652 
653     int err = ioctl(fd, ADF_SET_EVENT, &data);
654     if (err < 0)
655         return -errno;
656     return 0;
657 }
658 
adf_read_event(int fd,struct adf_event ** event)659 int adf_read_event(int fd, struct adf_event **event)
660 {
661     struct adf_event header;
662     struct {
663         struct adf_event base;
664         uint8_t data[0];
665     } *event_ret;
666     size_t data_size;
667     int ret = 0;
668 
669     int err = read(fd, &header, sizeof(header));
670     if (err < 0)
671         return -errno;
672     if ((size_t)err < sizeof(header))
673         return -EIO;
674     if (header.length < sizeof(header))
675         return -EIO;
676 
677     event_ret = malloc(header.length);
678     if (!event_ret)
679         return -ENOMEM;
680     data_size = header.length - sizeof(header);
681 
682     memcpy(event_ret, &header, sizeof(header));
683     ssize_t read_size = read(fd, &event_ret->data, data_size);
684     if (read_size < 0) {
685         ret = -errno;
686         goto done;
687     }
688     if ((size_t)read_size < data_size) {
689         ret = -EIO;
690         goto done;
691     }
692 
693     *event = &event_ret->base;
694 
695 done:
696     if (ret < 0)
697         free(event_ret);
698     return ret;
699 }
700 
adf_format_str(__u32 format,char buf[ADF_FORMAT_STR_SIZE])701 void adf_format_str(__u32 format, char buf[ADF_FORMAT_STR_SIZE])
702 {
703     buf[0] = format & 0xFF;
704     buf[1] = (format >> 8) & 0xFF;
705     buf[2] = (format >> 16) & 0xFF;
706     buf[3] = (format >> 24) & 0xFF;
707     buf[4] = '\0';
708 }
709 
adf_find_simple_post_overlay_engine(struct adf_device * dev,const __u32 * formats,size_t n_formats,adf_id_t interface,adf_id_t * overlay_engine)710 static bool adf_find_simple_post_overlay_engine(struct adf_device *dev,
711         const __u32 *formats, size_t n_formats,
712         adf_id_t interface, adf_id_t *overlay_engine)
713 {
714     adf_id_t *engs;
715     ssize_t n_engs = adf_overlay_engines_for_interface(dev, interface, &engs);
716 
717     if (n_engs <= 0)
718         return false;
719 
720     adf_id_t *filtered_engs;
721     ssize_t n_filtered_engs = adf_overlay_engines_filter_by_format(dev,
722             formats, n_formats, engs, n_engs, &filtered_engs);
723     free(engs);
724 
725     if (n_filtered_engs <= 0)
726         return false;
727 
728     *overlay_engine = filtered_engs[0];
729     free(filtered_engs);
730     return true;
731 }
732 
733 static const __u32 any_rgb_format[] = {
734     DRM_FORMAT_C8,
735     DRM_FORMAT_RGB332,
736     DRM_FORMAT_BGR233,
737     DRM_FORMAT_XRGB1555,
738     DRM_FORMAT_XBGR1555,
739     DRM_FORMAT_RGBX5551,
740     DRM_FORMAT_BGRX5551,
741     DRM_FORMAT_ARGB1555,
742     DRM_FORMAT_ABGR1555,
743     DRM_FORMAT_RGBA5551,
744     DRM_FORMAT_BGRA5551,
745     DRM_FORMAT_RGB565,
746     DRM_FORMAT_BGR565,
747     DRM_FORMAT_RGB888,
748     DRM_FORMAT_BGR888,
749     DRM_FORMAT_XRGB8888,
750     DRM_FORMAT_XBGR8888,
751     DRM_FORMAT_RGBX8888,
752     DRM_FORMAT_BGRX8888,
753     DRM_FORMAT_XRGB2101010,
754     DRM_FORMAT_XBGR2101010,
755     DRM_FORMAT_RGBX1010102,
756     DRM_FORMAT_BGRX1010102,
757     DRM_FORMAT_ARGB2101010,
758     DRM_FORMAT_ABGR2101010,
759     DRM_FORMAT_RGBA1010102,
760     DRM_FORMAT_BGRA1010102,
761     DRM_FORMAT_ARGB8888,
762     DRM_FORMAT_ABGR8888,
763     DRM_FORMAT_RGBA8888,
764     DRM_FORMAT_BGRA8888,
765 };
766 
adf_find_simple_post_configuration(struct adf_device * dev,const __u32 * formats,size_t n_formats,adf_id_t * interface,adf_id_t * overlay_engine)767 int adf_find_simple_post_configuration(struct adf_device *dev,
768         const __u32 *formats, size_t n_formats,
769         adf_id_t *interface, adf_id_t *overlay_engine)
770 {
771     adf_id_t *intfs = NULL;
772     ssize_t n_intfs = adf_interfaces(dev, &intfs);
773 
774     if (n_intfs < 0)
775         return n_intfs;
776     else if (!n_intfs)
777         return -ENODEV;
778 
779     adf_id_t *primary_intfs;
780     ssize_t n_primary_intfs = adf_interfaces_filter_by_flag(dev,
781             ADF_INTF_FLAG_PRIMARY, intfs, n_intfs, &primary_intfs);
782     free(intfs);
783 
784     if (n_primary_intfs < 0)
785         return n_primary_intfs;
786     else if (!n_primary_intfs)
787         return -ENODEV;
788 
789     if (!formats) {
790         formats = any_rgb_format;
791         n_formats = sizeof(any_rgb_format) / sizeof(any_rgb_format[0]);
792     }
793 
794     bool found = false;
795     ssize_t i = 0;
796     for (i = 0; i < n_primary_intfs; i++) {
797         found = adf_find_simple_post_overlay_engine(dev, formats, n_formats,
798                 primary_intfs[i], overlay_engine);
799         if (found) {
800             *interface = primary_intfs[i];
801             break;
802         }
803     }
804     free(primary_intfs);
805 
806     if (!found)
807         return -ENODEV;
808 
809     return 0;
810 }
811