blob: 10f88b0071c7437db2e869de42723a1e3e0358e0 [file] [log] [blame]
Greg Hackmannb85d12a2013-11-08 09:40:12 -08001/*
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>
Elliott Hughes3d74d7a2015-01-29 21:31:23 -080020#include <malloc.h>
Greg Hackmannb85d12a2013-11-08 09:40:12 -080021#include <stdint.h>
22#include <stdio.h>
23#include <string.h>
Elliott Hughes3d74d7a2015-01-29 21:31:23 -080024#include <unistd.h>
Greg Hackmannb85d12a2013-11-08 09:40:12 -080025
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
34static 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
73done:
74 closedir(dir);
75 if (ret < 0)
76 free(ids_ret);
77 else
78 *ids = ids_ret;
79 return ret;
80}
81
82ssize_t adf_devices(adf_id_t **ids)
83{
84 return adf_find_nodes("adf%u", ids);
85}
86
87int adf_device_open(adf_id_t id, int flags, struct adf_device *dev)
88{
89 char filename[64];
Greg Hackmannb85d12a2013-11-08 09:40:12 -080090
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
101void adf_device_close(struct adf_device *dev)
102{
103 if (dev->fd >= 0)
104 close(dev->fd);
105}
106
107int 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
147done:
148 if (ret < 0)
149 adf_free_device_data(data);
150 return ret;
151}
152
153void 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
160int 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
Greg Hackmann095da6f2016-07-25 14:49:30 -0700183int adf_device_post_v2(struct adf_device *dev,
184 adf_id_t *interfaces, __u32 n_interfaces,
185 struct adf_buffer_config *bufs, __u32 n_bufs,
186 void *custom_data, __u64 custom_data_size,
187 enum adf_complete_fence_type complete_fence_type,
188 int *complete_fence)
189{
190 int err;
191 struct adf_post_config_v2 data;
192
193 memset(&data, 0, sizeof(data));
194 data.interfaces = (uintptr_t)interfaces;
195 data.n_interfaces = n_interfaces;
196 data.bufs = (uintptr_t)bufs;
197 data.n_bufs = n_bufs;
198 data.custom_data = (uintptr_t)custom_data;
199 data.custom_data_size = custom_data_size;
200 data.complete_fence_type = complete_fence_type;
201
202 err = ioctl(dev->fd, ADF_POST_CONFIG_V2, &data);
203 if (err < 0)
204 return -errno;
205
206 if (complete_fence)
207 *complete_fence = data.complete_fence;
208 else if (data.complete_fence >= 0)
209 close(data.complete_fence);
210
211 return 0;
212}
213
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800214static int adf_device_attachment(struct adf_device *dev,
215 adf_id_t overlay_engine, adf_id_t interface, bool attach)
216{
217 int err;
218 struct adf_attachment_config data;
219
220 memset(&data, 0, sizeof(data));
221 data.overlay_engine = overlay_engine;
222 data.interface = interface;
223
224 err = ioctl(dev->fd, attach ? ADF_ATTACH : ADF_DETACH, &data);
225 if (err < 0)
226 return -errno;
227
228 return 0;
229}
230
231int adf_device_attach(struct adf_device *dev, adf_id_t overlay_engine,
232 adf_id_t interface)
233{
234 return adf_device_attachment(dev, overlay_engine, interface, true);
235}
236
237int adf_device_detach(struct adf_device *dev, adf_id_t overlay_engine,
238 adf_id_t interface)
239{
240 return adf_device_attachment(dev, overlay_engine, interface, false);
241}
242
243ssize_t adf_interfaces(struct adf_device *dev, adf_id_t **interfaces)
244{
245 char pattern[64];
246
247 snprintf(pattern, sizeof(pattern), "adf-interface%u.%%u", dev->id);
248 return adf_find_nodes(pattern, interfaces);
249}
250
251ssize_t adf_interfaces_for_overlay_engine(struct adf_device *dev,
252 adf_id_t overlay_engine, adf_id_t **interfaces)
253{
254 struct adf_device_data data;
255 ssize_t n = 0;
256 ssize_t ret;
257 adf_id_t *ids_ret = NULL;
258
259 ret = adf_get_device_data(dev, &data);
260 if (ret < 0)
261 return ret;
262
263 size_t i;
264 for (i = 0; i < data.n_allowed_attachments; i++) {
265 if (data.allowed_attachments[i].overlay_engine != overlay_engine)
266 continue;
267
268 adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
269 if (!new_ids) {
270 ret = -ENOMEM;
271 goto done;
272 }
273
274 ids_ret = new_ids;
275 ids_ret[n] = data.allowed_attachments[i].interface;
276 n++;
277 }
278
279 ret = n;
280
281done:
282 adf_free_device_data(&data);
283 if (ret < 0)
284 free(ids_ret);
285 else
286 *interfaces = ids_ret;
287 return ret;
288}
289
290static ssize_t adf_interfaces_filter(struct adf_device *dev,
291 adf_id_t *in, size_t n_in, adf_id_t **out,
292 bool (*filter)(struct adf_interface_data *data, __u32 match),
293 __u32 match)
294{
295 size_t n = 0;
296 ssize_t ret;
297 adf_id_t *ids_ret = NULL;
298
299 size_t i;
300 for (i = 0; i < n_in; i++) {
301 int fd = adf_interface_open(dev, in[i], O_RDONLY);
302 if (fd < 0) {
303 ret = fd;
304 goto done;
305 }
306
307 struct adf_interface_data data;
308 ret = adf_get_interface_data(fd, &data);
309 close(fd);
310 if (ret < 0)
311 goto done;
312
313 if (!filter(&data, match))
314 continue;
315
316 adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
317 if (!new_ids) {
318 ret = -ENOMEM;
319 goto done;
320 }
321
322 ids_ret = new_ids;
323 ids_ret[n] = in[i];
324 n++;
325 }
326
327 ret = n;
328
329done:
330 if (ret < 0)
331 free(ids_ret);
332 else
333 *out = ids_ret;
334 return ret;
335}
336
337static bool adf_interface_type_filter(struct adf_interface_data *data,
338 __u32 type)
339{
340 return data->type == (enum adf_interface_type)type;
341}
342
343ssize_t adf_interfaces_filter_by_type(struct adf_device *dev,
344 enum adf_interface_type type,
345 adf_id_t *in, size_t n_in, adf_id_t **out)
346{
347 return adf_interfaces_filter(dev, in, n_in, out, adf_interface_type_filter,
348 type);
349}
350
351static bool adf_interface_flags_filter(struct adf_interface_data *data,
352 __u32 flag)
353{
354 return !!(data->flags & flag);
355}
356
357ssize_t adf_interfaces_filter_by_flag(struct adf_device *dev, __u32 flag,
358 adf_id_t *in, size_t n_in, adf_id_t **out)
359{
360 return adf_interfaces_filter(dev, in, n_in, out, adf_interface_flags_filter,
361 flag);
362}
363
364int adf_interface_open(struct adf_device *dev, adf_id_t id, int flags)
365{
366 char filename[64];
367
368 snprintf(filename, sizeof(filename), ADF_BASE_PATH "adf-interface%u.%u",
369 dev->id, id);
370
371 int fd = open(filename, flags);
372 if (fd < 0)
373 return -errno;
374 return fd;
375}
376
377int adf_get_interface_data(int fd, struct adf_interface_data *data)
378{
379 int err;
380 int ret = 0;
381
382 memset(data, 0, sizeof(*data));
383
384 err = ioctl(fd, ADF_GET_INTERFACE_DATA, data);
385 if (err < 0)
386 return -errno;
387
388 if (data->n_available_modes) {
389 data->available_modes = malloc(sizeof(data->available_modes[0]) *
390 data->n_available_modes);
391 if (!data->available_modes)
392 return -ENOMEM;
393 }
394
395 if (data->custom_data_size) {
396 data->custom_data = malloc(data->custom_data_size);
397 if (!data->custom_data) {
398 ret = -ENOMEM;
399 goto done;
400 }
401 }
402
403 err = ioctl(fd, ADF_GET_INTERFACE_DATA, data);
404 if (err < 0)
405 ret = -errno;
406
407done:
408 if (ret < 0)
409 adf_free_interface_data(data);
410 return ret;
411}
412
413void adf_free_interface_data(struct adf_interface_data *data)
414{
415 free(data->available_modes);
416 free(data->custom_data);
417}
418
419int adf_interface_blank(int fd, __u8 mode)
420{
421 int err = ioctl(fd, ADF_BLANK, mode);
422 if (err < 0)
423 return -errno;
424 return 0;
425}
426
427int adf_interface_set_mode(int fd, struct drm_mode_modeinfo *mode)
428{
429 int err = ioctl(fd, ADF_SET_MODE, mode);
430 if (err < 0)
431 return -errno;
432 return 0;
433}
434
435int adf_interface_simple_buffer_alloc(int fd, __u32 w, __u32 h,
436 __u32 format, __u32 *offset, __u32 *pitch)
437{
438 int err;
439 struct adf_simple_buffer_alloc data;
440
441 memset(&data, 0, sizeof(data));
442 data.w = w;
443 data.h = h;
444 data.format = format;
445
446 err = ioctl(fd, ADF_SIMPLE_BUFFER_ALLOC, &data);
447 if (err < 0)
448 return -errno;
449
450 *offset = data.offset;
451 *pitch = data.pitch;
452 return (int)data.fd;
453}
454
Greg Hackmann095da6f2016-07-25 14:49:30 -0700455static void adf_interface_simple_post_config_buf(struct adf_buffer_config *buf,
456 __u32 overlay_engine, __u32 w, __u32 h, __u32 format, int buf_fd,
457 __u32 offset, __u32 pitch, int acquire_fence)
458{
459 buf->overlay_engine = overlay_engine;
460 buf->w = w;
461 buf->h = h;
462 buf->format = format;
463 buf->fd[0] = buf_fd;
464 buf->offset[0] = offset;
465 buf->pitch[0] = pitch;
466 buf->n_planes = 1;
467 buf->acquire_fence = acquire_fence;
468}
469
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800470int adf_interface_simple_post(int fd, __u32 overlay_engine,
471 __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset,
472 __u32 pitch, int acquire_fence)
473{
474 int ret;
475 struct adf_simple_post_config data;
476
477 memset(&data, 0, sizeof(data));
Greg Hackmann095da6f2016-07-25 14:49:30 -0700478 adf_interface_simple_post_config_buf(&data.buf, overlay_engine, w, h, format,
479 buf_fd, offset, pitch, acquire_fence);
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800480 ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG, &data);
481 if (ret < 0)
482 return -errno;
483
484 return (int)data.complete_fence;
485}
486
Greg Hackmann095da6f2016-07-25 14:49:30 -0700487int adf_interface_simple_post_v2(int fd, adf_id_t overlay_engine,
488 __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset,
489 __u32 pitch, int acquire_fence,
490 enum adf_complete_fence_type complete_fence_type,
491 int *complete_fence)
492{
493 int ret;
494 struct adf_simple_post_config_v2 data;
495
496 memset(&data, 0, sizeof(data));
497 adf_interface_simple_post_config_buf(&data.buf, overlay_engine, w, h, format,
498 buf_fd, offset, pitch, acquire_fence);
499 data.complete_fence_type = complete_fence_type;
500
501 ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG_V2, &data);
502 if (ret < 0)
503 return -errno;
504
505 if (complete_fence)
506 *complete_fence = data.complete_fence;
507 else if (data.complete_fence >= 0)
508 close(data.complete_fence);
509
510 return 0;
511}
512
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800513ssize_t adf_overlay_engines(struct adf_device *dev, adf_id_t **overlay_engines)
514{
515 char pattern[64];
516
517 snprintf(pattern, sizeof(pattern), "adf-overlay-engine%u.%%u", dev->id);
518 return adf_find_nodes(pattern, overlay_engines);
519}
520
521ssize_t adf_overlay_engines_for_interface(struct adf_device *dev,
522 adf_id_t interface, adf_id_t **overlay_engines)
523{
524 struct adf_device_data data;
525 ssize_t n = 0;
526 ssize_t ret;
527 adf_id_t *ids_ret = NULL;
528
529 ret = adf_get_device_data(dev, &data);
530 if (ret < 0)
531 return ret;
532
533 size_t i;
534 for (i = 0; i < data.n_allowed_attachments; i++) {
535 if (data.allowed_attachments[i].interface != interface)
536 continue;
537
538 adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
539 if (!new_ids) {
540 ret = -ENOMEM;
541 goto done;
542 }
543
544 ids_ret = new_ids;
545 ids_ret[n] = data.allowed_attachments[i].overlay_engine;
546 n++;
547 }
548
549 ret = n;
550
551done:
552 adf_free_device_data(&data);
553 if (ret < 0)
554 free(ids_ret);
555 else
556 *overlay_engines = ids_ret;
557 return ret;
558}
559
560static ssize_t adf_overlay_engines_filter(struct adf_device *dev,
561 adf_id_t *in, size_t n_in, adf_id_t **out,
Greg Hackmann47e0c8d2013-11-12 10:38:36 -0800562 bool (*filter)(struct adf_overlay_engine_data *data, void *cookie),
563 void *cookie)
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800564{
565 size_t n = 0;
566 ssize_t ret;
567 adf_id_t *ids_ret = NULL;
568
569 size_t i;
570 for (i = 0; i < n_in; i++) {
571 int fd = adf_overlay_engine_open(dev, in[i], O_RDONLY);
572 if (fd < 0) {
573 ret = fd;
574 goto done;
575 }
576
577 struct adf_overlay_engine_data data;
578 ret = adf_get_overlay_engine_data(fd, &data);
579 close(fd);
580 if (ret < 0)
581 goto done;
582
Greg Hackmann47e0c8d2013-11-12 10:38:36 -0800583 if (!filter(&data, cookie))
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800584 continue;
585
586 adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
587 if (!new_ids) {
588 ret = -ENOMEM;
589 goto done;
590 }
591
592 ids_ret = new_ids;
593 ids_ret[n] = in[i];
594 n++;
595 }
596
597 ret = n;
598
599done:
600 if (ret < 0)
601 free(ids_ret);
602 else
603 *out = ids_ret;
604 return ret;
605}
606
Greg Hackmann47e0c8d2013-11-12 10:38:36 -0800607struct format_filter_cookie {
608 const __u32 *formats;
609 size_t n_formats;
610};
611
612static bool adf_overlay_engine_format_filter(
613 struct adf_overlay_engine_data *data, void *cookie)
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800614{
Greg Hackmann47e0c8d2013-11-12 10:38:36 -0800615 struct format_filter_cookie *c = cookie;
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800616 size_t i;
Greg Hackmann47e0c8d2013-11-12 10:38:36 -0800617 for (i = 0; i < data->n_supported_formats; i++) {
618 size_t j;
619 for (j = 0; j < c->n_formats; j++)
620 if (data->supported_formats[i] == c->formats[j])
621 return true;
622 }
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800623 return false;
624}
625
626ssize_t adf_overlay_engines_filter_by_format(struct adf_device *dev,
Greg Hackmann47e0c8d2013-11-12 10:38:36 -0800627 const __u32 *formats, size_t n_formats, adf_id_t *in, size_t n_in,
628 adf_id_t **out)
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800629{
Greg Hackmann47e0c8d2013-11-12 10:38:36 -0800630 struct format_filter_cookie cookie = { formats, n_formats };
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800631 return adf_overlay_engines_filter(dev, in, n_in, out,
Greg Hackmann47e0c8d2013-11-12 10:38:36 -0800632 adf_overlay_engine_format_filter, &cookie);
Greg Hackmannb85d12a2013-11-08 09:40:12 -0800633}
634
635int adf_overlay_engine_open(struct adf_device *dev, adf_id_t id, int flags)
636{
637 char filename[64];
638
639 snprintf(filename, sizeof(filename),
640 ADF_BASE_PATH "adf-overlay-engine%u.%u", dev->id, id);
641
642 int fd = open(filename, flags);
643 if (fd < 0)
644 return -errno;
645 return fd;
646}
647
648int adf_get_overlay_engine_data(int fd, struct adf_overlay_engine_data *data)
649{
650 int err;
651 int ret = 0;
652
653 memset(data, 0, sizeof(*data));
654
655 err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data);
656 if (err < 0)
657 return -errno;
658
659 if (data->n_supported_formats) {
660 data->supported_formats = malloc(sizeof(data->supported_formats[0]) *
661 data->n_supported_formats);
662 if (!data->supported_formats)
663 return -ENOMEM;
664 }
665
666 if (data->custom_data_size) {
667 data->custom_data = malloc(data->custom_data_size);
668 if (!data->custom_data) {
669 ret = -ENOMEM;
670 goto done;
671 }
672 }
673
674 err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data);
675 if (err < 0)
676 ret = -errno;
677
678done:
679 if (ret < 0)
680 adf_free_overlay_engine_data(data);
681 return ret;
682}
683
684void adf_free_overlay_engine_data(struct adf_overlay_engine_data *data)
685{
686 free(data->supported_formats);
687 free(data->custom_data);
688}
689
690bool adf_overlay_engine_supports_format(int fd, __u32 format)
691{
692 struct adf_overlay_engine_data data;
693 bool ret = false;
694 size_t i;
695
696 int err = adf_get_overlay_engine_data(fd, &data);
697 if (err < 0)
698 return false;
699
700 for (i = 0; i < data.n_supported_formats; i++) {
701 if (data.supported_formats[i] == format) {
702 ret = true;
703 break;
704 }
705 }
706
707 adf_free_overlay_engine_data(&data);
708 return ret;
709}
710
711int adf_set_event(int fd, enum adf_event_type type, bool enabled)
712{
713 struct adf_set_event data;
714
715 data.type = type;
716 data.enabled = enabled;
717
718 int err = ioctl(fd, ADF_SET_EVENT, &data);
719 if (err < 0)
720 return -errno;
721 return 0;
722}
723
724int adf_read_event(int fd, struct adf_event **event)
725{
726 struct adf_event header;
727 struct {
728 struct adf_event base;
729 uint8_t data[0];
730 } *event_ret;
731 size_t data_size;
732 int ret = 0;
733
734 int err = read(fd, &header, sizeof(header));
735 if (err < 0)
736 return -errno;
737 if ((size_t)err < sizeof(header))
738 return -EIO;
739 if (header.length < sizeof(header))
740 return -EIO;
741
742 event_ret = malloc(header.length);
743 if (!event_ret)
744 return -ENOMEM;
745 data_size = header.length - sizeof(header);
746
747 memcpy(event_ret, &header, sizeof(header));
748 ssize_t read_size = read(fd, &event_ret->data, data_size);
749 if (read_size < 0) {
750 ret = -errno;
751 goto done;
752 }
753 if ((size_t)read_size < data_size) {
754 ret = -EIO;
755 goto done;
756 }
757
758 *event = &event_ret->base;
759
760done:
761 if (ret < 0)
762 free(event_ret);
763 return ret;
764}
765
766void adf_format_str(__u32 format, char buf[ADF_FORMAT_STR_SIZE])
767{
768 buf[0] = format & 0xFF;
769 buf[1] = (format >> 8) & 0xFF;
770 buf[2] = (format >> 16) & 0xFF;
771 buf[3] = (format >> 24) & 0xFF;
772 buf[4] = '\0';
773}
Greg Hackmann18326352013-11-12 10:39:35 -0800774
775static bool adf_find_simple_post_overlay_engine(struct adf_device *dev,
776 const __u32 *formats, size_t n_formats,
777 adf_id_t interface, adf_id_t *overlay_engine)
778{
779 adf_id_t *engs;
780 ssize_t n_engs = adf_overlay_engines_for_interface(dev, interface, &engs);
781
782 if (n_engs <= 0)
783 return false;
784
785 adf_id_t *filtered_engs;
786 ssize_t n_filtered_engs = adf_overlay_engines_filter_by_format(dev,
787 formats, n_formats, engs, n_engs, &filtered_engs);
788 free(engs);
789
790 if (n_filtered_engs <= 0)
791 return false;
792
793 *overlay_engine = filtered_engs[0];
794 free(filtered_engs);
795 return true;
796}
797
798static const __u32 any_rgb_format[] = {
799 DRM_FORMAT_C8,
800 DRM_FORMAT_RGB332,
801 DRM_FORMAT_BGR233,
802 DRM_FORMAT_XRGB1555,
803 DRM_FORMAT_XBGR1555,
804 DRM_FORMAT_RGBX5551,
805 DRM_FORMAT_BGRX5551,
806 DRM_FORMAT_ARGB1555,
807 DRM_FORMAT_ABGR1555,
808 DRM_FORMAT_RGBA5551,
809 DRM_FORMAT_BGRA5551,
810 DRM_FORMAT_RGB565,
811 DRM_FORMAT_BGR565,
812 DRM_FORMAT_RGB888,
813 DRM_FORMAT_BGR888,
814 DRM_FORMAT_XRGB8888,
815 DRM_FORMAT_XBGR8888,
816 DRM_FORMAT_RGBX8888,
817 DRM_FORMAT_BGRX8888,
818 DRM_FORMAT_XRGB2101010,
819 DRM_FORMAT_XBGR2101010,
820 DRM_FORMAT_RGBX1010102,
821 DRM_FORMAT_BGRX1010102,
822 DRM_FORMAT_ARGB2101010,
823 DRM_FORMAT_ABGR2101010,
824 DRM_FORMAT_RGBA1010102,
825 DRM_FORMAT_BGRA1010102,
826 DRM_FORMAT_ARGB8888,
827 DRM_FORMAT_ABGR8888,
828 DRM_FORMAT_RGBA8888,
829 DRM_FORMAT_BGRA8888,
830};
831
832int adf_find_simple_post_configuration(struct adf_device *dev,
833 const __u32 *formats, size_t n_formats,
834 adf_id_t *interface, adf_id_t *overlay_engine)
835{
Greg Hackmann20fcb782014-05-07 14:55:30 -0700836 adf_id_t *intfs = NULL;
Greg Hackmann18326352013-11-12 10:39:35 -0800837 ssize_t n_intfs = adf_interfaces(dev, &intfs);
838
839 if (n_intfs < 0)
840 return n_intfs;
841 else if (!n_intfs)
842 return -ENODEV;
843
844 adf_id_t *primary_intfs;
845 ssize_t n_primary_intfs = adf_interfaces_filter_by_flag(dev,
846 ADF_INTF_FLAG_PRIMARY, intfs, n_intfs, &primary_intfs);
847 free(intfs);
848
849 if (n_primary_intfs < 0)
850 return n_primary_intfs;
851 else if (!n_primary_intfs)
852 return -ENODEV;
853
854 if (!formats) {
855 formats = any_rgb_format;
856 n_formats = sizeof(any_rgb_format) / sizeof(any_rgb_format[0]);
857 }
858
859 bool found = false;
860 ssize_t i = 0;
861 for (i = 0; i < n_primary_intfs; i++) {
862 found = adf_find_simple_post_overlay_engine(dev, formats, n_formats,
863 primary_intfs[i], overlay_engine);
864 if (found) {
865 *interface = primary_intfs[i];
866 break;
867 }
868 }
869 free(primary_intfs);
870
871 if (!found)
872 return -ENODEV;
873
874 return 0;
875}