Home | History | Annotate | Download | only in libadf
      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 
     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 
     82 ssize_t adf_devices(adf_id_t **ids)
     83 {
     84     return adf_find_nodes("adf%u", ids);
     85 }
     86 
     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 
    101 void adf_device_close(struct adf_device *dev)
    102 {
    103     if (dev->fd >= 0)
    104         close(dev->fd);
    105 }
    106 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    320 static bool adf_interface_flags_filter(struct adf_interface_data *data,
    321         __u32 flag)
    322 {
    323     return !!(data->flags & flag);
    324 }
    325 
    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 
    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 
    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 
    382 void adf_free_interface_data(struct adf_interface_data *data)
    383 {
    384     free(data->available_modes);
    385     free(data->custom_data);
    386 }
    387 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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