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 <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 
     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 
     80 ssize_t adf_devices(adf_id_t **ids)
     81 {
     82     return adf_find_nodes("adf%u", ids);
     83 }
     84 
     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 
    100 void adf_device_close(struct adf_device *dev)
    101 {
    102     if (dev->fd >= 0)
    103         close(dev->fd);
    104 }
    105 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    319 static bool adf_interface_flags_filter(struct adf_interface_data *data,
    320         __u32 flag)
    321 {
    322     return !!(data->flags & flag);
    323 }
    324 
    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 
    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 
    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 
    381 void adf_free_interface_data(struct adf_interface_data *data)
    382 {
    383     free(data->available_modes);
    384     free(data->custom_data);
    385 }
    386 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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