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