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