1 /**************************************************************************
5 Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
35 #include "tdm_backend_vc4.h"
37 #define LIST_INSERT_AFTER(__after, __item) \
38 (__item)->prev = (__after); \
39 (__item)->next = (__after)->next; \
40 (__after)->next->prev = (__item); \
41 (__after)->next = (__item);
43 static drmModeModeInfoPtr
44 _tdm_vc4_display_get_mode(tdm_vc4_output *output_data)
48 if (!output_data->current_mode) {
49 TDM_BACKEND_ERR("no output_data->current_mode");
53 const hal_tdm_output_mode *mode;
55 mode = output_data->current_mode;
56 TDM_BACKEND_INFO("Current mode: %s, %d, %d, %d, %d, %d",
57 mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
60 TDM_BACKEND_INFO(" Count modes: %d %d", output_data->count_drm_modes, output_data->count_modes);
62 for (i = 0; i < output_data->count_drm_modes; i++) {
63 drmModeModeInfoPtr vc4_mode = &output_data->vc4_modes[i];
65 TDM_BACKEND_INFO(" DRM mode: %s, %d, %d, %d, %d, %d",
66 vc4_mode->name, vc4_mode->hdisplay, vc4_mode->vdisplay, vc4_mode->vrefresh, vc4_mode->flags, vc4_mode->type);
68 if ((vc4_mode->hdisplay == output_data->current_mode->hdisplay) &&
69 (vc4_mode->hsync_start == output_data->current_mode->hsync_start) &&
70 (vc4_mode->hsync_end == output_data->current_mode->hsync_end) &&
71 (vc4_mode->htotal == output_data->current_mode->htotal) &&
72 (vc4_mode->hskew == output_data->current_mode->hskew) &&
73 (vc4_mode->vdisplay == output_data->current_mode->vdisplay) &&
74 (vc4_mode->vsync_start == output_data->current_mode->vsync_start) &&
75 (vc4_mode->vsync_end == output_data->current_mode->vsync_end) &&
76 (vc4_mode->vtotal == output_data->current_mode->vtotal) &&
77 (vc4_mode->vscan == output_data->current_mode->vscan) &&
78 (vc4_mode->clock == output_data->current_mode->clock) &&
79 (vc4_mode->vrefresh == output_data->current_mode->vrefresh) &&
80 (vc4_mode->flags == output_data->current_mode->flags) &&
81 (vc4_mode->type == output_data->current_mode->type) &&
82 !(strncmp(vc4_mode->name, output_data->current_mode->name, HAL_TDM_NAME_LEN)))
90 _tdm_vc4_display_set_fb(tdm_vc4_display *display_data, tbm_surface_h buffer, unsigned int *id)
95 unsigned int handles[4] = {0,};
96 unsigned int pitches[4] = {0,};
97 unsigned int offsets[4] = {0,};
102 width = tbm_surface_get_width(buffer);
103 height = tbm_surface_get_height(buffer);
104 format = tbm_surface_get_format(buffer);
105 count = tbm_surface_internal_get_num_bos(buffer);
106 for (i = 0; i < count; i++) {
107 tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
108 handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
110 count = tbm_surface_internal_get_num_planes(format);
111 for (i = 0; i < count; i++)
112 tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
114 TDM_BACKEND_DBG("AddFB2: drm_fd(%d) size(%dx%d) format(%c%c%c%c) handles(%d,%d,%d) pitches(%d,%d,%d) offsets(%d,%d,%d) buffer(%p)",
115 display_data->drm_fd, width, height, FOURCC_STR(format),
116 handles[0], handles[1], handles[2], pitches[0], pitches[1], pitches[2],
117 offsets[0], offsets[1], offsets[2], buffer);
119 ret = drmModeAddFB2(display_data->drm_fd, width, height, format,
120 handles, pitches, offsets, &fb_id, 0);
122 TDM_BACKEND_ERR("add fb failed: %m");
123 return HAL_TDM_ERROR_OPERATION_FAILED;
125 TDM_BACKEND_DBG("AddFB2 success: drm_fd(%d) fb_id(%u)", display_data->drm_fd, fb_id);
128 return HAL_TDM_ERROR_NONE;
132 _tdm_vc4_output_update_status(tdm_vc4_output *output_data,
133 hal_tdm_output_conn_status status)
135 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
137 if (output_data->status == status)
138 return HAL_TDM_ERROR_NONE;
140 output_data->status = status;
142 if (output_data->status_func)
143 output_data->status_func(output_data, status,
144 output_data->status_user_data);
146 return HAL_TDM_ERROR_NONE;
150 _tdm_vc4_display_set_crtc(tdm_vc4_display *display_data, tdm_vc4_output *output_data, int set)
154 output_data->mode_changed = 0;
157 tbm_surface_h buffer = NULL;
158 tbm_surface_info_s info;
159 drmModeModeInfoPtr mode;
160 unsigned int fb_id = 0;
162 if (!output_data->current_mode)
163 return HAL_TDM_ERROR_OPERATION_FAILED;
165 mode = _tdm_vc4_display_get_mode(output_data);
167 TDM_BACKEND_ERR("couldn't find proper mode");
168 return HAL_TDM_ERROR_BAD_REQUEST;
171 buffer = tbm_surface_create(output_data->current_mode->hdisplay,
172 output_data->current_mode->vdisplay,
173 TBM_FORMAT_XRGB8888);
174 TDM_BACKEND_RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_OPERATION_FAILED);
176 if (tbm_surface_map(buffer, TBM_SURF_OPTION_WRITE, &info) != TBM_ERROR_NONE) {
177 tbm_surface_destroy(buffer);
178 return HAL_TDM_ERROR_OPERATION_FAILED;
180 memset(info.planes[0].ptr, 0x0, info.size);
182 tbm_surface_unmap(buffer);
184 if (_tdm_vc4_display_set_fb(display_data, buffer, &fb_id) != HAL_TDM_ERROR_NONE) {
185 tbm_surface_destroy(buffer);
186 return HAL_TDM_ERROR_OPERATION_FAILED;
189 TDM_BACKEND_DBG("drmModeSetCrtc drm_fd(%d) crtc_id(%u) fb_id(%u) mode(%u,%u)",
190 display_data->drm_fd, output_data->crtc_id, fb_id,
191 mode->hdisplay, mode->vdisplay);
193 if (drmModeSetCrtc(display_data->drm_fd, output_data->crtc_id,
195 &output_data->connector_id, 1, mode)) {
196 TDM_BACKEND_ERR("set crtc failed: %m");
197 ret = drmModeRmFB(display_data->drm_fd, fb_id);
199 TDM_BACKEND_ERR("rm fb failed fb_id(%u)", fb_id);
200 tbm_surface_destroy(buffer);
201 return HAL_TDM_ERROR_OPERATION_FAILED;
204 _tdm_vc4_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
205 output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED;
207 if (output_data->crtc_buffer) {
208 ret = drmModeRmFB(display_data->drm_fd, output_data->crtc_fb_id);
210 TDM_BACKEND_ERR("rm fb failed fb_id(%u)", output_data->crtc_fb_id);
211 tbm_surface_destroy(output_data->crtc_buffer);
213 output_data->crtc_buffer = buffer;
214 output_data->crtc_fb_id = fb_id;
216 TDM_BACKEND_DBG("drmModeSetCrtc unset drm_fd(%d) crtc_id(%u)",
217 display_data->drm_fd, output_data->crtc_id);
219 if (drmModeSetCrtc(display_data->drm_fd, output_data->crtc_id,
220 0, 0, 0, NULL, 0, NULL)) {
221 TDM_BACKEND_ERR("unset crtc failed: %m");
222 return HAL_TDM_ERROR_OPERATION_FAILED;
225 if (output_data->crtc_buffer) {
226 ret = drmModeRmFB(display_data->drm_fd, output_data->crtc_fb_id);
228 TDM_BACKEND_ERR("rm fb failed fb_id(%u)", output_data->crtc_fb_id);
229 tbm_surface_destroy(output_data->crtc_buffer);
231 output_data->crtc_buffer = NULL;
232 output_data->crtc_fb_id = 0;
235 return HAL_TDM_ERROR_NONE;
239 _tdm_vc4_display_to_tdm_mode(drmModeModeInfoPtr vc4_mode,
240 hal_tdm_output_mode *tdm_mode)
242 tdm_mode->clock = vc4_mode->clock;
243 tdm_mode->hdisplay = vc4_mode->hdisplay;
244 tdm_mode->hsync_start = vc4_mode->hsync_start;
245 tdm_mode->hsync_end = vc4_mode->hsync_end;
246 tdm_mode->htotal = vc4_mode->htotal;
247 tdm_mode->hskew = vc4_mode->hskew;
248 tdm_mode->vdisplay = vc4_mode->vdisplay;
249 tdm_mode->vsync_start = vc4_mode->vsync_start;
250 tdm_mode->vsync_end = vc4_mode->vsync_end;
251 tdm_mode->vtotal = vc4_mode->vtotal;
252 tdm_mode->vscan = vc4_mode->vscan;
253 tdm_mode->vrefresh = vc4_mode->vrefresh;
254 tdm_mode->flags = vc4_mode->flags;
255 tdm_mode->type = vc4_mode->type;
256 snprintf(tdm_mode->name, HAL_TDM_NAME_LEN, "%s", vc4_mode->name);
260 _tdm_vc4_display_get_cur_msc(int fd, int pipe, uint *msc)
264 vbl.request.type = DRM_VBLANK_RELATIVE;
266 vbl.request.type |= DRM_VBLANK_SECONDARY;
268 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
270 vbl.request.sequence = 0;
271 if (drmWaitVBlank(fd, &vbl)) {
272 TDM_BACKEND_ERR("get vblank counter failed: %m");
274 return HAL_TDM_ERROR_OPERATION_FAILED;
277 *msc = vbl.reply.sequence;
279 return HAL_TDM_ERROR_NONE;
283 _tdm_vc4_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
287 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
289 vbl.request.type |= DRM_VBLANK_SECONDARY;
291 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
293 vbl.request.sequence = *target_msc;
294 vbl.request.signal = (unsigned long)(uintptr_t)data;
296 if (drmWaitVBlank(fd, &vbl)) {
297 TDM_BACKEND_ERR("wait vblank failed: %m");
299 return HAL_TDM_ERROR_OPERATION_FAILED;
302 *target_msc = vbl.reply.sequence;
304 return HAL_TDM_ERROR_NONE;
308 _tdm_vc4_display_commit_layer(tdm_vc4_layer *layer_data)
310 tdm_vc4_display *display_data = layer_data->display_data;
311 tdm_vc4_output *output_data = layer_data->output_data;
312 uint32_t fx, fy, fw, fh;
315 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
316 return HAL_TDM_ERROR_NONE;
318 if (!output_data->crtc_enabled || output_data->mode_changed) {
319 if (_tdm_vc4_display_set_crtc(display_data, output_data, 1) != HAL_TDM_ERROR_NONE)
320 return HAL_TDM_ERROR_OPERATION_FAILED;
322 output_data->crtc_enabled = 1;
325 if (output_data->current_mode)
326 crtc_w = output_data->current_mode->hdisplay;
328 drmModeCrtcPtr crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id);
330 TDM_BACKEND_ERR("getting crtc failed");
331 return HAL_TDM_ERROR_OPERATION_FAILED;
333 crtc_w = crtc->width;
335 TDM_BACKEND_ERR("getting crtc width failed");
336 drmModeFreeCrtc(crtc);
337 return HAL_TDM_ERROR_OPERATION_FAILED;
339 drmModeFreeCrtc(crtc);
342 layer_data->display_buffer_changed = 0;
343 layer_data->info_changed = 0;
345 if (!layer_data->display_buffer) {
346 if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id,
347 output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
348 TDM_BACKEND_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
350 return HAL_TDM_ERROR_NONE;
353 /* Source values are 16.16 fixed point */
354 fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
355 fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
356 fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
357 fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
359 if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id,
360 output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
361 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
362 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
363 fx, fy, fw, fh) < 0) {
364 TDM_BACKEND_ERR("set plane(%d) failed: %m", layer_data->plane_id);
365 return HAL_TDM_ERROR_OPERATION_FAILED;
368 TDM_BACKEND_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
369 layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
370 layer_data->display_buffer->fb_id,
371 layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
372 layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
373 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
374 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
376 return HAL_TDM_ERROR_NONE;
380 _tdm_vc4_display_cb_event(int fd, unsigned int sequence,
381 unsigned int tv_sec, unsigned int tv_usec,
384 tdm_vc4_event *event_data = user_data;
385 tdm_vc4_output *output_data;
386 tdm_vc4_hwc *hwc_data;
390 TDM_BACKEND_ERR("no event data");
394 output_data = event_data->output_data;
396 TDM_BACKEND_DBG("==== Event Callback on pipe, %u, crtc_id, %u connector_id, %u",
397 output_data->pipe, output_data->crtc_id, output_data->connector_id);
399 switch (event_data->type) {
400 case TDM_DRM_EVENT_TYPE_PAGEFLIP:
401 TDM_BACKEND_DBG("==== TDM_DRM_EVENT_TYPE_PAGEFLIP");
403 if (output_data->commit_func)
404 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
405 event_data->user_data);
407 case TDM_DRM_EVENT_TYPE_WAIT:
408 TDM_BACKEND_DBG("==== TDM_DRM_EVENT_TYPE_WAIT");
410 if (output_data->vblank_func)
411 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
412 event_data->user_data);
414 case TDM_DRM_EVENT_TYPE_COMMIT:
415 TDM_BACKEND_DBG("==== TDM_DRM_EVENT_TYPE_COMMIT");
417 hwc_data = output_data->hwc_data;
420 TDM_BACKEND_ERR("no hwc_data");
424 if (hwc_data->commit_func)
425 hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec,
426 event_data->user_data);
429 TDM_BACKEND_ERR("Wrong event type");
437 _vc4_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id)
439 drmModeObjectPropertiesPtr properties = NULL;
440 drmModePropertyPtr property = NULL;
443 properties = drmModeObjectGetProperties(drm_fd, object_id, object_type);
444 if (properties == NULL) {
445 TDM_BACKEND_ERR("drmModeObjectGetProperties failed");
446 return HAL_TDM_ERROR_OPERATION_FAILED;
449 for (i = 0; i < properties->count_props; i++) {
450 property = drmModeGetProperty(drm_fd, properties->props[i]);
451 if (property == NULL) {
455 if (strcmp(property->name, name) == 0) {
456 *id = property->prop_id;
457 drmModeFreeProperty(property);
460 drmModeFreeProperty(property);
463 drmModeFreeObjectProperties(properties);
465 return HAL_TDM_ERROR_NONE;
469 _tdm_vc4_display_create_layer_list(tdm_vc4_display *display_data)
471 tdm_vc4_output *output_data = NULL;
474 if (LIST_IS_EMPTY(&display_data->output_list)) {
475 TDM_BACKEND_ERR("no output");
476 return HAL_TDM_ERROR_OPERATION_FAILED;
479 /* The TDM drm backend only support one output. */
480 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
484 if (display_data->plane_res->count_planes == 0) {
485 TDM_BACKEND_ERR("no layer_data error");
486 return HAL_TDM_ERROR_OPERATION_FAILED;
489 for (i = 0; i < display_data->plane_res->count_planes; i++) {
490 tdm_vc4_layer *layer_data;
491 drmModePlanePtr plane;
493 plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]);
495 TDM_BACKEND_ERR("no plane");
499 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
500 drmModeFreePlane(plane);
504 layer_data = calloc(1, sizeof(tdm_vc4_layer));
506 TDM_BACKEND_ERR("alloc failed");
507 drmModeFreePlane(plane);
511 layer_data->display_data = display_data;
512 layer_data->output_data = output_data;
513 layer_data->plane_id = display_data->plane_res->planes[i];
514 layer_data->acquire_fence = -1;
516 layer_data->capabilities = TDM_VC4_LAYER_CAPABILITY_PRIMARY |
517 TDM_VC4_LAYER_CAPABILITY_GRAPHIC;
518 output_data->primary_layer = layer_data;
520 TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
521 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
522 layer_data->capabilities);
524 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
526 drmModeFreePlane(plane);
528 /* can't take care of other planes for various hardware devices */
532 return HAL_TDM_ERROR_NONE;
535 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
538 _tdm_vc4_display_get_property(tdm_vc4_display *display_data,
539 unsigned int obj_id, unsigned int obj_type,
540 const char *name, unsigned int *value,
543 drmModeObjectPropertiesPtr props = NULL;
546 props = drmModeObjectGetProperties(display_data->drm_fd, obj_id, obj_type);
548 return HAL_TDM_ERROR_OPERATION_FAILED;
550 for (i = 0; i < props->count_props; i++) {
551 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd,
557 if (!strcmp(prop->name, name)) {
559 *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
561 *value = (unsigned int)props->prop_values[i];
562 drmModeFreeProperty(prop);
563 drmModeFreeObjectProperties(props);
564 return HAL_TDM_ERROR_NONE;
567 drmModeFreeProperty(prop);
569 drmModeFreeObjectProperties(props);
570 TDM_BACKEND_DBG("coundn't find '%s' property", name);
571 return HAL_TDM_ERROR_OPERATION_FAILED;
575 _tdm_vc4_display_create_layer_list_type(tdm_vc4_display *display_data)
577 drmModePlanePtr plane;
581 for (i = 0; i < display_data->plane_res->count_planes; i++) {
582 tdm_vc4_output *output_data = NULL;
583 tdm_vc4_layer *layer_data;
584 unsigned int type = 0;
587 plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]);
589 TDM_BACKEND_ERR("no plane");
593 ret = _tdm_vc4_display_get_property(display_data,
594 display_data->plane_res->planes[i],
595 DRM_MODE_OBJECT_PLANE, "type", &type, NULL);
596 if (ret != HAL_TDM_ERROR_NONE) {
597 TDM_BACKEND_ERR("plane(%d) doesn't have 'type' info",
598 display_data->plane_res->planes[i]);
599 drmModeFreePlane(plane);
603 layer_data = calloc(1, sizeof(tdm_vc4_layer));
605 TDM_BACKEND_ERR("alloc failed");
606 drmModeFreePlane(plane);
610 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
611 if (plane->possible_crtcs & (1 << output_data->pipe)) {
612 if (type == DRM_PLANE_TYPE_CURSOR) {
613 if (output_data->cursor_layer)
615 } else if (type == DRM_PLANE_TYPE_OVERLAY) {
616 if (output_data->overlay_layer)
618 } else if (type == DRM_PLANE_TYPE_PRIMARY) {
619 if (output_data->primary_layer)
629 TDM_BACKEND_ERR("plane(%d) couldn't found proper output", plane->plane_id);
630 drmModeFreePlane(plane);
635 layer_data->display_data = display_data;
636 layer_data->output_data = output_data;
637 layer_data->plane_id = display_data->plane_res->planes[i];
638 layer_data->acquire_fence = -1;
640 if (type == DRM_PLANE_TYPE_CURSOR) {
641 layer_data->capabilities = TDM_VC4_LAYER_CAPABILITY_CURSOR |
642 TDM_VC4_LAYER_CAPABILITY_GRAPHIC;
643 layer_data->zpos = 2;
644 output_data->cursor_layer = layer_data;
645 } else if (type == DRM_PLANE_TYPE_OVERLAY) {
646 layer_data->capabilities = TDM_VC4_LAYER_CAPABILITY_OVERLAY |
647 TDM_VC4_LAYER_CAPABILITY_GRAPHIC;
648 layer_data->zpos = 1;
649 output_data->overlay_layer = layer_data;
650 } else if (type == DRM_PLANE_TYPE_PRIMARY) {
651 layer_data->capabilities = TDM_VC4_LAYER_CAPABILITY_PRIMARY |
652 TDM_VC4_LAYER_CAPABILITY_GRAPHIC;
653 layer_data->zpos = 0;
654 output_data->primary_layer = layer_data;
656 drmModeFreePlane(plane);
661 TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
662 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
663 layer_data->zpos, layer_data->capabilities);
665 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
667 /* get the atomic prop ids*/
668 if (display_data->has_atomic) {
669 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
670 DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id);
671 if (ret != HAL_TDM_ERROR_NONE) {
673 goto failed_atomic_prop_id;
676 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
677 DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id);
678 if (ret != HAL_TDM_ERROR_NONE) {
680 goto failed_atomic_prop_id;
683 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
684 DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x);
685 if (ret != HAL_TDM_ERROR_NONE) {
687 goto failed_atomic_prop_id;
690 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
691 DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y);
692 if (ret != HAL_TDM_ERROR_NONE) {
694 goto failed_atomic_prop_id;
697 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
698 DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w);
699 if (ret != HAL_TDM_ERROR_NONE) {
701 goto failed_atomic_prop_id;
704 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
705 DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h);
706 if (ret != HAL_TDM_ERROR_NONE) {
708 goto failed_atomic_prop_id;
711 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
712 DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x);
713 if (ret != HAL_TDM_ERROR_NONE) {
715 goto failed_atomic_prop_id;
718 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
719 DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y);
720 if (ret != HAL_TDM_ERROR_NONE) {
722 goto failed_atomic_prop_id;
725 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
726 DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w);
727 if (ret != HAL_TDM_ERROR_NONE) {
729 goto failed_atomic_prop_id;
732 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
733 DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h);
734 if (ret != HAL_TDM_ERROR_NONE) {
736 goto failed_atomic_prop_id;
739 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
740 DRM_MODE_OBJECT_PLANE, "IN_FENCE_FD", &layer_data->atomic_props_ids.in_fence_fd);
741 if (ret != HAL_TDM_ERROR_NONE) {
743 goto failed_atomic_prop_id;
747 drmModeFreePlane(plane);
750 return HAL_TDM_ERROR_NONE;
752 failed_atomic_prop_id:
754 drmModeFreePlane(plane);
756 return HAL_TDM_ERROR_OPERATION_FAILED;
761 _get_primary_layer_zpos(tdm_vc4_output *output_data)
763 tdm_vc4_layer *layer_data = NULL;
765 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
766 if (layer_data->capabilities & TDM_VC4_LAYER_CAPABILITY_PRIMARY)
767 return layer_data->zpos;
774 tdm_vc4_display_create_layer_list(tdm_vc4_display *display_data)
776 tdm_vc4_output *output_data = NULL;
779 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
780 if (display_data->has_universal_plane)
781 ret = _tdm_vc4_display_create_layer_list_type(display_data);
784 ret = _tdm_vc4_display_create_layer_list(display_data);
786 if (ret != HAL_TDM_ERROR_NONE)
789 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
790 if (!output_data->primary_layer) {
791 TDM_BACKEND_ERR("output(%d) no primary layer_data", output_data->pipe);
792 return HAL_TDM_ERROR_OPERATION_FAILED;
796 return HAL_TDM_ERROR_NONE;
800 tdm_vc4_display_destroy_output_list(tdm_vc4_display *display_data)
802 tdm_vc4_output *o = NULL, *oo = NULL;
803 tdm_vc4_hwc *hwc_data = NULL;
805 if (LIST_IS_EMPTY(&display_data->output_list))
808 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &display_data->output_list, link) {
809 hwc_data = o->hwc_data;
810 if (hwc_data && hwc_data->target_hwc_window)
811 vc4_hwc_window_destroy(hwc_data->target_hwc_window);
813 if (o->crtc_enabled) {
814 _tdm_vc4_display_set_crtc(display_data, o, 0);
819 if (!LIST_IS_EMPTY(&o->layer_list)) {
820 tdm_vc4_layer *l = NULL, *ll = NULL;
821 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
823 if (l->display_buffer)
824 tbm_surface_internal_unref(l->display_buffer->buffer);
829 free(o->output_modes);
835 tdm_vc4_display_update_output_status(tdm_vc4_display *display_data)
837 tdm_vc4_output *output_data = NULL;
839 if (LIST_IS_EMPTY(&display_data->output_list))
842 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
843 drmModeConnectorPtr connector;
844 hal_tdm_output_conn_status new_status;
846 connector = drmModeGetConnector(display_data->drm_fd,
847 output_data->connector_id);
849 TDM_BACKEND_ERR("no connector: %d", output_data->connector_id);
853 if (connector->connection == DRM_MODE_CONNECTED)
854 new_status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED;
856 new_status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
858 _tdm_vc4_output_update_status(output_data, new_status);
860 drmModeFreeConnector(connector);
865 tdm_vc4_display_create_output_list(tdm_vc4_display *display_data)
867 tdm_vc4_output *output_data;
872 TDM_BACKEND_RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&display_data->output_list),
873 HAL_TDM_ERROR_OPERATION_FAILED);
875 for (i = 0; i < display_data->mode_res->count_connectors; i++) {
876 drmModeConnectorPtr connector;
877 drmModeEncoderPtr encoder;
878 int crtc_id = 0, c, j;
880 connector = drmModeGetConnector(display_data->drm_fd,
881 display_data->mode_res->connectors[i]);
883 TDM_BACKEND_ERR("no connector");
884 ret = HAL_TDM_ERROR_OPERATION_FAILED;
888 if (connector->count_encoders != 1) {
889 TDM_BACKEND_ERR("too many encoders: %d", connector->count_encoders);
890 drmModeFreeConnector(connector);
891 ret = HAL_TDM_ERROR_OPERATION_FAILED;
895 encoder = drmModeGetEncoder(display_data->drm_fd, connector->encoders[0]);
897 TDM_BACKEND_ERR("no encoder");
898 drmModeFreeConnector(connector);
899 ret = HAL_TDM_ERROR_OPERATION_FAILED;
903 for (c = 0; c < display_data->mode_res->count_crtcs; c++) {
904 if (allocated & (1 << c))
907 if ((encoder->possible_crtcs & (1 << c)) == 0)
910 crtc_id = display_data->mode_res->crtcs[c];
911 allocated |= (1 << c);
916 TDM_BACKEND_ERR("no possible crtc");
917 drmModeFreeConnector(connector);
918 drmModeFreeEncoder(encoder);
919 ret = HAL_TDM_ERROR_OPERATION_FAILED;
923 output_data = calloc(1, sizeof(tdm_vc4_output));
925 TDM_BACKEND_ERR("alloc failed");
926 drmModeFreeConnector(connector);
927 drmModeFreeEncoder(encoder);
928 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
932 LIST_INITHEAD(&output_data->layer_list);
934 output_data->display_data = display_data;
935 output_data->connector_id = display_data->mode_res->connectors[i];
936 output_data->encoder_id = encoder->encoder_id;
937 output_data->crtc_id = crtc_id;
938 output_data->pipe = c;
939 output_data->connector_type = connector->connector_type;
940 output_data->connector_type_id = connector->connector_type_id;
941 output_data->commit_fence = -1;
943 if (connector->connection == DRM_MODE_CONNECTED)
944 output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED;
946 output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
948 for (j = 0; j < connector->count_props; j++) {
949 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd,
950 connector->props[j]);
953 if (!strcmp(prop->name, "DPMS")) {
954 output_data->dpms_prop_id = connector->props[j];
955 drmModeFreeProperty(prop);
958 drmModeFreeProperty(prop);
961 output_data->count_modes = connector->count_modes;
962 output_data->vc4_modes = calloc(connector->count_modes, sizeof(drmModeModeInfo));
963 if (!output_data->vc4_modes) {
964 TDM_BACKEND_ERR("alloc failed");
966 drmModeFreeConnector(connector);
967 drmModeFreeEncoder(encoder);
968 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
972 output_data->output_modes = calloc(connector->count_modes, sizeof(hal_tdm_output_mode));
973 if (!output_data->output_modes) {
974 TDM_BACKEND_ERR("alloc failed");
975 free(output_data->vc4_modes);
977 drmModeFreeConnector(connector);
978 drmModeFreeEncoder(encoder);
979 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
983 for (j = 0; j < connector->count_modes; j++) {
984 output_data->vc4_modes[j] = connector->modes[j];
985 _tdm_vc4_display_to_tdm_mode(&output_data->vc4_modes[j],
986 &output_data->output_modes[j]);
989 LIST_ADDTAIL(&output_data->link, &display_data->output_list);
991 TDM_BACKEND_INFO("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d) count_modes(%d)",
992 output_data, output_data->connector_id, output_data->status,
993 output_data->connector_type,
994 output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
995 output_data->pipe, output_data->dpms_prop_id, output_data->count_modes);
997 drmModeFreeEncoder(encoder);
998 drmModeFreeConnector(connector);
1000 /* get the atomic prop ids*/
1001 if (display_data->has_atomic) {
1002 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, output_data->connector_id,
1003 DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id);
1004 if (ret != HAL_TDM_ERROR_NONE)
1005 goto failed_atomic_prop_id;
1007 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id,
1008 DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id);
1009 if (ret != HAL_TDM_ERROR_NONE)
1010 goto failed_atomic_prop_id;
1012 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id,
1013 DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active);
1014 if (ret != HAL_TDM_ERROR_NONE)
1015 goto failed_atomic_prop_id;
1017 ret = _vc4_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id,
1018 DRM_MODE_OBJECT_CRTC, "OUT_FENCE_PTR", &output_data->atomic_props_ids.out_fence_ptr);
1019 if (ret != HAL_TDM_ERROR_NONE)
1020 goto failed_atomic_prop_id;
1024 TDM_BACKEND_INFO("output count: %d", display_data->mode_res->count_connectors);
1026 return HAL_TDM_ERROR_NONE;
1027 failed_atomic_prop_id:
1029 tdm_vc4_display_destroy_output_list(display_data);
1034 vc4_display_get_capability(hal_tdm_display *display, hal_tdm_caps_display *caps)
1036 TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
1038 caps->max_layer_count = -1; /* not defined */
1040 return HAL_TDM_ERROR_NONE;
1044 vc4_display_get_outputs(hal_tdm_display *display, int *count, hal_tdm_error *error)
1046 tdm_vc4_display *display_data = display;
1047 tdm_vc4_output *output_data = NULL;
1048 hal_tdm_output **outputs;
1052 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, NULL);
1053 TDM_BACKEND_RETURN_VAL_IF_FAIL(count, NULL);
1056 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link)
1060 ret = HAL_TDM_ERROR_NONE;
1064 /* will be freed in frontend */
1065 outputs = calloc(*count, sizeof(tdm_vc4_output *));
1067 TDM_BACKEND_ERR("failed: alloc memory");
1069 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1074 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link)
1075 outputs[i++] = output_data;
1078 *error = HAL_TDM_ERROR_NONE;
1088 vc4_display_get_fd(hal_tdm_display *display, int *fd)
1090 tdm_vc4_display *display_data = display;
1092 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1093 TDM_BACKEND_RETURN_VAL_IF_FAIL(fd, HAL_TDM_ERROR_INVALID_PARAMETER);
1095 *fd = display_data->drm_fd;
1097 return HAL_TDM_ERROR_NONE;
1101 vc4_display_handle_events(hal_tdm_display *display)
1103 tdm_vc4_display *display_data = display;
1104 drmEventContext ctx;
1106 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1108 memset(&ctx, 0, sizeof(drmEventContext));
1110 ctx.version = DRM_EVENT_CONTEXT_VERSION;
1111 ctx.page_flip_handler = _tdm_vc4_display_cb_event;
1112 ctx.vblank_handler = _tdm_vc4_display_cb_event;
1114 drmHandleEvent(display_data->drm_fd, &ctx);
1116 return HAL_TDM_ERROR_NONE;
1120 vc4_output_get_capability(hal_tdm_output *output, hal_tdm_caps_output *caps)
1122 tdm_vc4_output *output_data = output;
1123 tdm_vc4_display *display_data;
1124 drmModeConnectorPtr connector = NULL;
1125 drmModeCrtcPtr crtc = NULL;
1126 drmModeObjectPropertiesPtr props = NULL;
1130 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1131 TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
1133 memset(caps, 0, sizeof(hal_tdm_caps_output));
1135 display_data = output_data->display_data;
1137 snprintf(caps->maker, HAL_TDM_NAME_LEN, "unknown");
1138 snprintf(caps->model, HAL_TDM_NAME_LEN, "unknown");
1139 snprintf(caps->name, HAL_TDM_NAME_LEN, "unknown");
1141 caps->status = output_data->status;
1142 caps->type = output_data->connector_type;
1143 caps->type_id = output_data->connector_type_id;
1145 connector = drmModeGetConnector(display_data->drm_fd, output_data->connector_id);
1146 TDM_BACKEND_RETURN_VAL_IF_FAIL(connector, HAL_TDM_ERROR_OPERATION_FAILED);
1148 caps->mode_count = connector->count_modes;
1149 if (caps->mode_count != 0) {
1150 caps->modes = calloc(1, sizeof(hal_tdm_output_mode) * caps->mode_count);
1152 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1153 TDM_BACKEND_ERR("alloc failed\n");
1157 output_data->count_drm_modes = connector->count_modes;
1158 output_data->count_modes = caps->mode_count;
1160 drmModeModeInfoPtr new_drm_modes;
1161 hal_tdm_output_mode *new_output_modes;
1163 new_drm_modes = calloc(connector->count_modes,
1164 sizeof(drmModeModeInfo));
1165 if (!new_drm_modes) {
1166 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1167 TDM_BACKEND_ERR("alloc failed drm_modes\n");
1170 new_output_modes = calloc(caps->mode_count,
1171 sizeof(hal_tdm_output_mode));
1172 if (!new_output_modes) {
1173 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1174 TDM_BACKEND_ERR("alloc failed output_modes\n");
1175 free(new_drm_modes);
1178 if (output_data->vc4_modes)
1179 free(output_data->vc4_modes);
1180 if (output_data->output_modes)
1181 free(output_data->output_modes);
1183 output_data->vc4_modes = new_drm_modes;
1184 output_data->output_modes = new_output_modes;
1186 for (i = 0; i < connector->count_modes; i++) {
1187 output_data->vc4_modes[i] = connector->modes[i];
1188 _tdm_vc4_display_to_tdm_mode(&output_data->vc4_modes[i],
1189 &output_data->output_modes[i]);
1190 caps->modes[i] = output_data->output_modes[i];
1194 output_data->count_drm_modes = connector->count_modes;
1195 output_data->count_modes = caps->mode_count;
1197 if (output_data->vc4_modes)
1198 free(output_data->vc4_modes);
1199 if (output_data->output_modes)
1200 free(output_data->output_modes);
1202 output_data->vc4_modes = NULL;
1203 output_data->output_modes = NULL;
1206 caps->mmWidth = connector->mmWidth;
1207 caps->mmHeight = connector->mmHeight;
1208 caps->subpixel = connector->subpixel;
1210 caps->min_w = display_data->mode_res->min_width;
1211 caps->min_h = display_data->mode_res->min_height;
1212 caps->max_w = display_data->mode_res->max_width;
1213 caps->max_h = display_data->mode_res->max_height;
1214 caps->preferred_align = -1;
1216 crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id);
1218 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1219 TDM_BACKEND_ERR("get crtc failed: %m\n");
1223 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id,
1224 DRM_MODE_OBJECT_CRTC);
1226 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1227 TDM_BACKEND_ERR("get crtc properties failed: %m\n");
1231 caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props);
1233 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1234 TDM_BACKEND_ERR("alloc failed\n");
1238 caps->prop_count = 0;
1239 for (i = 0; i < props->count_props; i++) {
1240 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]);
1243 snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name);
1244 caps->props[caps->prop_count].id = props->props[i];
1246 drmModeFreeProperty(prop);
1249 // enable tdm_hwc and mirror
1250 caps->capabilities |= HAL_TDM_OUTPUT_CAPABILITY_HWC;
1251 caps->capabilities |= HAL_TDM_OUTPUT_CAPABILITY_MIRROR;
1253 drmModeFreeObjectProperties(props);
1254 drmModeFreeCrtc(crtc);
1255 drmModeFreeConnector(connector);
1257 return HAL_TDM_ERROR_NONE;
1259 drmModeFreeCrtc(crtc);
1260 drmModeFreeObjectProperties(props);
1261 drmModeFreeConnector(connector);
1264 memset(caps, 0, sizeof(hal_tdm_caps_output));
1269 vc4_output_set_property(hal_tdm_output *output, unsigned int id, hal_tdm_value value)
1271 tdm_vc4_output *output_data = output;
1272 tdm_vc4_display *display_data;
1275 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1276 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1278 display_data = output_data->display_data;
1279 ret = drmModeObjectSetProperty(display_data->drm_fd,
1280 output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
1283 TDM_BACKEND_ERR("set property failed: %m");
1284 return HAL_TDM_ERROR_OPERATION_FAILED;
1287 return HAL_TDM_ERROR_NONE;
1291 vc4_output_get_property(hal_tdm_output *output, unsigned int id, hal_tdm_value *value)
1293 tdm_vc4_output *output_data = output;
1294 tdm_vc4_display *display_data;
1295 drmModeObjectPropertiesPtr props;
1298 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1299 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1300 TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER);
1302 display_data = output_data->display_data;
1303 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id,
1304 DRM_MODE_OBJECT_CRTC);
1305 if (props == NULL) {
1306 TDM_BACKEND_ERR("get property failed: %m");
1307 return HAL_TDM_ERROR_OPERATION_FAILED;
1310 for (i = 0; i < props->count_props; i++)
1311 if (props->props[i] == id) {
1312 (*value).u32 = (uint)props->prop_values[i];
1316 drmModeFreeObjectProperties(props);
1318 return HAL_TDM_ERROR_NONE;
1322 vc4_output_wait_vblank(hal_tdm_output *output, int interval, int sync,
1325 tdm_vc4_output *output_data = output;
1326 tdm_vc4_display *display_data;
1327 tdm_vc4_event *event_data;
1331 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1333 event_data = calloc(1, sizeof(tdm_vc4_event));
1335 TDM_BACKEND_ERR("alloc failed");
1336 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1339 display_data = output_data->display_data;
1341 ret = _tdm_vc4_display_get_cur_msc(display_data->drm_fd, output_data->pipe,
1343 if (ret != HAL_TDM_ERROR_NONE)
1346 target_msc += interval;
1348 event_data->type = TDM_DRM_EVENT_TYPE_WAIT;
1349 event_data->output_data = output_data;
1350 event_data->user_data = user_data;
1352 ret = _tdm_vc4_display_wait_vblank(display_data->drm_fd, output_data->pipe,
1353 &target_msc, event_data);
1354 if (ret != HAL_TDM_ERROR_NONE)
1357 return HAL_TDM_ERROR_NONE;
1364 vc4_output_set_vblank_handler(hal_tdm_output *output,
1365 hal_tdm_output_vblank_handler func)
1367 tdm_vc4_output *output_data = output;
1369 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1370 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1372 output_data->vblank_func = func;
1374 return HAL_TDM_ERROR_NONE;
1377 static hal_tdm_error
1378 _vc4_layer_add_atomic_properties(tdm_vc4_layer *layer_data, drmModeAtomicReqPtr request,
1379 uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
1380 uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h, int acquire_fence)
1382 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1384 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id);
1386 TDM_BACKEND_ERR("fail to add the atomic prop. fb_id(%u)", fb_id);
1387 return HAL_TDM_ERROR_OPERATION_FAILED;
1390 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id);
1392 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id);
1393 return HAL_TDM_ERROR_OPERATION_FAILED;
1396 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x);
1398 TDM_BACKEND_ERR("fail to add the atomic prop. src_x(%u)", src_x);
1399 return HAL_TDM_ERROR_OPERATION_FAILED;
1402 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y);
1404 TDM_BACKEND_ERR("fail to add the atomic prop. src_y(%u)", src_y);
1405 return HAL_TDM_ERROR_OPERATION_FAILED;
1408 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w);
1410 TDM_BACKEND_ERR("fail to add the atomic prop. src_w(%u)", src_w);
1411 return HAL_TDM_ERROR_OPERATION_FAILED;
1414 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h);
1416 TDM_BACKEND_ERR("fail to add the atomic prop. src_h(%u)", src_h);
1417 return HAL_TDM_ERROR_OPERATION_FAILED;
1420 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x);
1422 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x);
1423 return HAL_TDM_ERROR_OPERATION_FAILED;
1426 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y);
1428 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y);
1429 return HAL_TDM_ERROR_OPERATION_FAILED;
1432 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w);
1434 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w);
1435 return HAL_TDM_ERROR_OPERATION_FAILED;
1438 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h);
1440 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h);
1441 return HAL_TDM_ERROR_OPERATION_FAILED;
1444 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.in_fence_fd, acquire_fence);
1446 TDM_BACKEND_ERR("fail to add the atomic prop. acquire_fence(%d)", acquire_fence);
1447 return HAL_TDM_ERROR_OPERATION_FAILED;
1450 return HAL_TDM_ERROR_NONE;
1453 static hal_tdm_error
1454 _vc4_layer_make_atomic_request(tdm_vc4_layer *layer_data, drmModeAtomicReqPtr request)
1456 tdm_vc4_display *display_data = layer_data->display_data;
1457 tdm_vc4_output *output_data = layer_data->output_data;
1458 uint32_t fx, fy, fw, fh;
1459 tdm_vc4_layer_info layer_info = layer_data->info;
1460 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1462 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
1463 return HAL_TDM_ERROR_NONE;
1465 layer_data->display_buffer_changed = 0;
1466 layer_data->info_changed = 0;
1468 if (!layer_data->display_buffer) {
1469 TDM_BACKEND_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off",
1470 display_data->drm_fd, layer_data->plane_id, output_data->crtc_id);
1472 ret = _vc4_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1);
1473 if (ret != HAL_TDM_ERROR_NONE) {
1474 TDM_BACKEND_ERR("_vc4_layer_add_atomic_properties failed.");
1478 return HAL_TDM_ERROR_NONE;
1481 /* Source values are 16.16 fixed point */
1482 fx = ((unsigned int)layer_info.src_config.pos.x) << 16;
1483 fy = ((unsigned int)layer_info.src_config.pos.y) << 16;
1484 fw = ((unsigned int)layer_info.src_config.pos.w) << 16;
1485 fh = ((unsigned int)layer_info.src_config.pos.h) << 16;
1487 TDM_BACKEND_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u)",
1488 display_data->drm_fd, layer_data->plane_id, layer_data->zpos,
1489 output_data->crtc_id, layer_data->display_buffer->fb_id,
1490 layer_info.src_config.pos.x, layer_info.src_config.pos.y,
1491 layer_info.src_config.pos.w, layer_info.src_config.pos.h,
1492 layer_info.dst_pos.x, layer_info.dst_pos.y,
1493 layer_info.dst_pos.w, layer_info.dst_pos.h);
1495 ret = _vc4_layer_add_atomic_properties(layer_data, request,
1496 layer_data->display_buffer->fb_id, output_data->crtc_id,
1498 layer_info.dst_pos.x, layer_info.dst_pos.y,
1499 layer_info.dst_pos.w, layer_info.dst_pos.h, layer_data->acquire_fence);
1500 if (ret != HAL_TDM_ERROR_NONE) {
1501 TDM_BACKEND_ERR("MakeAtomicRequest failed");
1505 return HAL_TDM_ERROR_NONE;
1508 static hal_tdm_error
1509 _vc4_output_make_atomic_request(tdm_vc4_output *output_data, drmModeAtomicReqPtr request,
1510 int *out_fence_fd, uint32_t *flags)
1512 drmModeModeInfoPtr current_mode;
1515 if (!output_data->crtc_enabled || output_data->mode_changed) {
1516 current_mode = _tdm_vc4_display_get_mode(output_data);
1517 if (!current_mode) {
1518 TDM_BACKEND_ERR("couldn't find proper mode");
1519 return HAL_TDM_ERROR_BAD_REQUEST;
1522 if (output_data->current_mode_blob_id > 0)
1523 drmModeDestroyPropertyBlob(output_data->display_data->drm_fd, output_data->current_mode_blob_id);
1525 if (drmModeCreatePropertyBlob(output_data->display_data->drm_fd, current_mode,
1526 sizeof(drmModeModeInfo), &output_data->current_mode_blob_id)) {
1527 TDM_BACKEND_ERR("fail to drmModeCreatePropertyBlob mode");
1528 return HAL_TDM_ERROR_OPERATION_FAILED;
1531 ret = drmModeAtomicAddProperty(request, output_data->connector_id,
1532 output_data->atomic_props_ids.crtc_id, output_data->crtc_id);
1534 TDM_BACKEND_ERR("fail to set crtc error:%d", errno);
1538 ret = drmModeAtomicAddProperty(request, output_data->crtc_id,
1539 output_data->atomic_props_ids.crtc_mode_id, output_data->current_mode_blob_id);
1541 TDM_BACKEND_ERR("fail to set mode error:%d", errno);
1545 ret = drmModeAtomicAddProperty(request, output_data->crtc_id,
1546 output_data->atomic_props_ids.crtc_active, 1);
1548 TDM_BACKEND_ERR("fail to set active error:%d", errno);
1552 output_data->crtc_enabled = 1;
1553 output_data->mode_changed = 0;
1555 _tdm_vc4_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
1557 *flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
1560 ret = drmModeAtomicAddProperty(request, output_data->crtc_id,
1561 output_data->atomic_props_ids.out_fence_ptr, (uintptr_t)out_fence_fd);
1563 TDM_BACKEND_ERR("fail to out fence ptr error:%d", errno);
1567 return HAL_TDM_ERROR_NONE;
1570 static hal_tdm_error
1571 _vc4_output_atomic_commit(hal_tdm_output *output, int sync, void *user_data)
1573 tdm_vc4_output *output_data = output;
1574 tdm_vc4_layer *layer_data = NULL;
1575 tdm_vc4_event *event_data;
1576 drmModeAtomicReqPtr request;
1579 int out_fence_fd = -1;
1581 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1583 request = drmModeAtomicAlloc();
1585 TDM_BACKEND_ERR("drmModeAtomicAlloc failed.");
1586 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1589 flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
1591 ret = _vc4_output_make_atomic_request(output_data, request, &out_fence_fd, &flags);
1592 if (ret != HAL_TDM_ERROR_NONE) {
1593 TDM_BACKEND_ERR("_vc4_output_make_atomic_request failed.");
1594 drmModeAtomicFree(request);
1598 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1599 ret = _vc4_layer_make_atomic_request(layer_data, request);
1600 if (ret != HAL_TDM_ERROR_NONE) {
1601 TDM_BACKEND_ERR("_vc4_layer_make_atomic_request failed.");
1602 drmModeAtomicFree(request);
1607 event_data = calloc(1, sizeof(tdm_vc4_event));
1609 TDM_BACKEND_ERR("fail to alloc event_data.");
1610 drmModeAtomicFree(request);
1611 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1614 event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
1615 event_data->output_data = output_data;
1616 event_data->user_data = user_data;
1618 TDM_BACKEND_DBG("==== Atomic Commit pipe, %u, crtc_id, %u connector_id, %u",
1619 output_data->pipe, output_data->crtc_id, output_data->connector_id);
1621 if (drmModeAtomicCommit(output_data->display_data->drm_fd, request, flags, event_data) < 0) {
1622 TDM_BACKEND_ERR("drmModeAtomicCommit failed.");
1623 drmModeAtomicFree(request);
1624 return HAL_TDM_ERROR_OPERATION_FAILED;
1627 if (output_data->commit_fence >= 0)
1628 close(output_data->commit_fence);
1630 output_data->commit_fence = out_fence_fd;
1632 drmModeAtomicFree(request);
1634 return HAL_TDM_ERROR_NONE;
1637 static hal_tdm_error
1638 _vc4_output_layers_commit(hal_tdm_output *output, int sync, void *user_data)
1640 tdm_vc4_output *output_data = output;
1641 tdm_vc4_display *display_data;
1642 tdm_vc4_layer *layer_data = NULL;
1644 int do_waitvblank = 1;
1646 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1648 display_data = output_data->display_data;
1650 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1651 ret = _tdm_vc4_display_commit_layer(layer_data);
1652 if (ret != HAL_TDM_ERROR_NONE)
1656 if (do_waitvblank == 1) {
1657 tdm_vc4_event *event_data = calloc(1, sizeof(tdm_vc4_event));
1661 TDM_BACKEND_ERR("alloc failed");
1662 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1665 ret = _tdm_vc4_display_get_cur_msc(display_data->drm_fd, output_data->pipe,
1667 if (ret != HAL_TDM_ERROR_NONE) {
1674 event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
1675 event_data->output_data = output_data;
1676 event_data->user_data = user_data;
1678 ret = _tdm_vc4_display_wait_vblank(display_data->drm_fd, output_data->pipe,
1679 &target_msc, event_data);
1680 if (ret != HAL_TDM_ERROR_NONE) {
1686 return HAL_TDM_ERROR_NONE;
1690 vc4_output_commit(hal_tdm_output *output, int sync, void *user_data)
1692 tdm_vc4_output *output_data = output;
1693 tdm_vc4_display *display_data;
1694 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1696 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1698 display_data = output_data->display_data;
1700 /* check the atomic pageflip */
1701 if (display_data->has_atomic) {
1702 ret = _vc4_output_atomic_commit(output, sync, user_data);
1703 if (ret != HAL_TDM_ERROR_NONE) {
1704 TDM_BACKEND_ERR("_vc4_output_atomic_commit failed.");
1708 ret = _vc4_output_layers_commit(output, sync, user_data);
1709 if (ret != HAL_TDM_ERROR_NONE) {
1710 TDM_BACKEND_ERR("_vc4_output_layers_commit failed.");
1715 return HAL_TDM_ERROR_NONE;
1719 vc4_output_set_commit_handler(hal_tdm_output *output,
1720 hal_tdm_output_commit_handler func)
1722 tdm_vc4_output *output_data = output;
1724 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1725 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1727 output_data->commit_func = func;
1729 return HAL_TDM_ERROR_NONE;
1733 vc4_output_set_dpms(hal_tdm_output *output, hal_tdm_output_dpms dpms_value)
1735 tdm_vc4_output *output_data = output;
1736 tdm_vc4_display *display_data;
1739 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1741 if (output_data->dpms_prop_id == 0) {
1742 TDM_BACKEND_WRN("not support DPMS");
1743 return HAL_TDM_ERROR_OPERATION_FAILED;
1746 display_data = output_data->display_data;
1747 ret = drmModeObjectSetProperty(display_data->drm_fd,
1748 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1749 output_data->dpms_prop_id, dpms_value);
1751 TDM_BACKEND_ERR("set dpms failed: %m");
1752 return HAL_TDM_ERROR_OPERATION_FAILED;
1755 return HAL_TDM_ERROR_NONE;
1759 vc4_output_get_dpms(hal_tdm_output *output, hal_tdm_output_dpms *dpms_value)
1761 tdm_vc4_output *output_data = output;
1762 tdm_vc4_display *display_data;
1763 drmModeObjectPropertiesPtr props;
1766 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1767 TDM_BACKEND_RETURN_VAL_IF_FAIL(dpms_value, HAL_TDM_ERROR_INVALID_PARAMETER);
1769 display_data = output_data->display_data;
1770 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->connector_id,
1771 DRM_MODE_OBJECT_CONNECTOR);
1772 if (props == NULL) {
1773 TDM_BACKEND_ERR("get property failed: %m");
1774 return HAL_TDM_ERROR_OPERATION_FAILED;
1777 for (i = 0; i < props->count_props; i++)
1778 if (props->props[i] == output_data->dpms_prop_id) {
1779 *dpms_value = (uint)props->prop_values[i];
1783 drmModeFreeObjectProperties(props);
1785 return HAL_TDM_ERROR_NONE;
1789 vc4_output_set_mode(hal_tdm_output *output, const hal_tdm_output_mode *mode)
1791 tdm_vc4_output *output_data = output;
1792 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1794 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1795 TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER);
1797 /* create or replace the target_window when the output mode is set */
1798 ret = tdm_vc4_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
1799 if (ret != HAL_TDM_ERROR_NONE) {
1800 TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret);
1804 output_data->current_mode = mode;
1805 output_data->mode_changed = 1;
1807 TDM_BACKEND_INFO("Set the output mode: %s, %d, %d, %d, %d, %d",
1808 mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
1810 ret = _tdm_vc4_display_set_crtc(output_data->display_data, output_data, 1);
1811 if (ret != HAL_TDM_ERROR_NONE) {
1812 TDM_BACKEND_ERR("fail to set crtc.");
1813 return HAL_TDM_ERROR_OPERATION_FAILED;
1815 output_data->crtc_enabled = 1;
1817 return HAL_TDM_ERROR_NONE;
1821 vc4_output_get_mode(hal_tdm_output *output, const hal_tdm_output_mode **mode)
1823 tdm_vc4_output *output_data = output;
1825 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1826 TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER);
1828 *mode = output_data->current_mode;
1830 return HAL_TDM_ERROR_NONE;
1834 vc4_output_set_mirror(hal_tdm_output *output, hal_tdm_output *src_output, hal_tdm_transform transform)
1836 tdm_vc4_output *output_data = (tdm_vc4_output *)output;
1837 tdm_vc4_output *src_output_data = (tdm_vc4_output *)src_output;
1839 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1840 TDM_BACKEND_RETURN_VAL_IF_FAIL(src_output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1842 output_data->mirror_src_output_data = src_output_data;
1843 src_output_data->mirror_dst_output_data = output_data;
1844 src_output_data->mirror_dst_transform = transform;
1846 TDM_BACKEND_INFO("Set the mirror. transform(%d)", transform);
1848 return HAL_TDM_ERROR_NONE;
1852 vc4_output_unset_mirror(hal_tdm_output *output)
1854 tdm_vc4_output *output_data = (tdm_vc4_output *)output;
1855 tdm_vc4_output *src_output_data;
1857 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1859 src_output_data = output_data->mirror_src_output_data;
1861 src_output_data->mirror_dst_transform = HAL_TDM_TRANSFORM_NORMAL;
1862 src_output_data->mirror_dst_output_data = NULL;
1863 output_data->mirror_src_output_data = NULL;
1865 TDM_BACKEND_INFO("Unet the mirror.");
1867 return HAL_TDM_ERROR_NONE;
1871 vc4_output_get_hwc(hal_tdm_output *output, hal_tdm_error *error)
1873 tdm_vc4_hwc *hwc_data = NULL;
1874 tdm_vc4_output *output_data = output;
1875 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1878 TDM_BACKEND_ERR("invalid params");
1880 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
1884 if (output_data->hwc_data) {
1885 TDM_BACKEND_INFO("hwc_data already exists");
1887 *error = HAL_TDM_ERROR_NONE;
1888 return output_data->hwc_data;
1891 hwc_data = calloc(1, sizeof(tdm_vc4_hwc));
1893 TDM_BACKEND_ERR("alloc failed");
1895 *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
1898 hwc_data->output_data = output_data;
1900 LIST_INITHEAD(&hwc_data->hwc_window_list);
1902 output_data->hwc_data = hwc_data;
1904 ret = tdm_vc4_hwc_initailize_target_window(output_data->hwc_data);
1905 if (ret != HAL_TDM_ERROR_NONE) {
1906 TDM_BACKEND_ERR("create target hwc window failed (%d)", ret);
1914 *error = HAL_TDM_ERROR_NONE;
1921 vc4_output_set_status_handler(hal_tdm_output *output,
1922 hal_tdm_output_status_handler func,
1925 tdm_vc4_output *output_data = output;
1927 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1928 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1930 output_data->status_func = func;
1931 output_data->status_user_data = user_data;
1933 return HAL_TDM_ERROR_NONE;
1937 tdm_vc4_layer_get_capability(tdm_vc4_layer *layer_data, tdm_vc4_caps_layer *caps)
1939 tdm_vc4_display *display_data;
1940 drmModePlanePtr plane = NULL;
1941 drmModeObjectPropertiesPtr props = NULL;
1942 int i, format_count = 0;
1943 int primary_zpos = _get_primary_layer_zpos(layer_data->output_data);
1946 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1947 TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
1949 memset(caps, 0, sizeof(tdm_vc4_caps_layer));
1951 display_data = layer_data->display_data;
1952 plane = drmModeGetPlane(display_data->drm_fd, layer_data->plane_id);
1954 TDM_BACKEND_ERR("get plane failed: %m");
1955 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1959 caps->capabilities = layer_data->capabilities;
1960 caps->zpos = layer_data->zpos;
1962 caps->format_count = plane->count_formats;
1963 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1964 if (!caps->formats) {
1965 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1966 TDM_BACKEND_ERR("alloc failed\n");
1970 for (i = 0; i < caps->format_count; i++) {
1971 /* Changing between RGB and YUV format for a plane doesn't work properly
1972 * only support AR24, XR24 for primary, overlay
1974 if (layer_data->zpos >= primary_zpos) {
1975 if (plane->formats[i] != DRM_FORMAT_XRGB8888 && plane->formats[i] != DRM_FORMAT_ARGB8888)
1978 /* only support NV12 for underlay */
1979 if (plane->formats[i] != DRM_FORMAT_NV12)
1983 caps->formats[format_count] = tdm_format_get_tbm_format(plane->formats[i]);
1987 caps->format_count = format_count;
1989 props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id,
1990 DRM_MODE_OBJECT_PLANE);
1992 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1993 TDM_BACKEND_ERR("get plane properties failed: %m\n");
1997 caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props);
1999 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
2000 TDM_BACKEND_ERR("alloc failed\n");
2004 caps->prop_count = 0;
2005 for (i = 0; i < props->count_props; i++) {
2006 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]);
2009 if (!strncmp(prop->name, "type", HAL_TDM_NAME_LEN)) {
2010 drmModeFreeProperty(prop);
2013 if (!strncmp(prop->name, "zpos", HAL_TDM_NAME_LEN)) {
2014 drmModeFreeProperty(prop);
2017 snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name);
2018 caps->props[caps->prop_count].id = props->props[i];
2020 drmModeFreeProperty(prop);
2023 drmModeFreeObjectProperties(props);
2024 drmModeFreePlane(plane);
2026 return HAL_TDM_ERROR_NONE;
2028 drmModeFreeObjectProperties(props);
2029 drmModeFreePlane(plane);
2030 free(caps->formats);
2032 memset(caps, 0, sizeof(tdm_vc4_caps_layer));
2037 tdm_vc4_layer_set_property(tdm_vc4_layer *layer_data, unsigned int id, hal_tdm_value value)
2039 tdm_vc4_display *display_data;
2042 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2043 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
2045 display_data = layer_data->display_data;
2046 ret = drmModeObjectSetProperty(display_data->drm_fd,
2047 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
2050 TDM_BACKEND_ERR("set property failed: %m");
2051 return HAL_TDM_ERROR_OPERATION_FAILED;
2054 return HAL_TDM_ERROR_NONE;
2058 tdm_vc4_layer_get_property(tdm_vc4_layer *layer_data, unsigned int id, hal_tdm_value *value)
2060 tdm_vc4_display *display_data;
2061 drmModeObjectPropertiesPtr props;
2064 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2065 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
2066 TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER);
2068 display_data = layer_data->display_data;
2069 props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id,
2070 DRM_MODE_OBJECT_PLANE);
2071 if (props == NULL) {
2072 TDM_BACKEND_ERR("get property failed: %m");
2073 return HAL_TDM_ERROR_OPERATION_FAILED;
2076 for (i = 0; i < props->count_props; i++)
2077 if (props->props[i] == id) {
2078 (*value).u32 = (uint)props->prop_values[i];
2082 drmModeFreeObjectProperties(props);
2084 return HAL_TDM_ERROR_NONE;
2088 tdm_vc4_layer_set_info(tdm_vc4_layer *layer_data, tdm_vc4_layer_info *info)
2090 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2091 TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
2093 layer_data->info = *info;
2094 layer_data->info_changed = 1;
2096 return HAL_TDM_ERROR_NONE;
2100 tdm_vc4_layer_get_info(tdm_vc4_layer *layer_data, tdm_vc4_layer_info *info)
2102 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2103 TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
2105 *info = layer_data->info;
2107 return HAL_TDM_ERROR_NONE;
2110 static tdm_vc4_display_buffer *
2111 _tdm_vc4_display_find_buffer(tdm_vc4_display *display_data, tbm_surface_h buffer)
2113 tdm_vc4_display_buffer *display_buffer = NULL;
2115 LIST_FOR_EACH_ENTRY(display_buffer, &display_data->buffer_list, link) {
2116 if (display_buffer->buffer == buffer)
2117 return display_buffer;
2124 _tdm_vc4_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
2126 tdm_vc4_display *display_data;
2127 tdm_vc4_display_buffer *display_buffer;
2128 tdm_vc4_layer *layer_data = NULL;
2129 tdm_vc4_output *output_data = NULL;
2130 char buf[256] = {0,};
2134 TDM_BACKEND_ERR("no user_data");
2138 TDM_BACKEND_ERR("no buffer");
2142 display_data = (tdm_vc4_display *) user_data;
2144 display_buffer = _tdm_vc4_display_find_buffer(display_data, buffer);
2145 if (!display_buffer) {
2146 TDM_BACKEND_ERR("no display_buffer");
2150 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
2151 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
2152 if (display_buffer == layer_data->display_buffer)
2153 layer_data->display_buffer = NULL;
2157 if (display_buffer->fb_id > 0) {
2158 if (drmModeRmFB(display_data->drm_fd, display_buffer->fb_id) < 0) {
2159 ret_tmp = strerror_r(errno, buf, sizeof(buf));
2160 TDM_BACKEND_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
2164 TDM_BACKEND_DBG("destroy buffer:%p", display_buffer->buffer);
2166 LIST_DEL(&display_buffer->link);
2167 free(display_buffer);
2170 static tdm_vc4_display_buffer *
2171 _tdm_vc4_display_create_buffer(tdm_vc4_display *display_data, tbm_surface_h buffer, hal_tdm_error *err)
2173 tdm_vc4_display_buffer *display_buffer = NULL;
2176 display_buffer = calloc(1, sizeof(tdm_vc4_display_buffer));
2177 if (!display_buffer) {
2178 TDM_BACKEND_ERR("alloc failed");
2180 *err = HAL_TDM_ERROR_OUT_OF_MEMORY;
2184 display_buffer->buffer = buffer;
2186 ret = tbm_surface_internal_add_destroy_handler(buffer, _tdm_vc4_display_cb_destroy_buffer, display_data);
2188 TDM_BACKEND_ERR("add destroy handler fail");
2189 free(display_buffer);
2191 *err = HAL_TDM_ERROR_OPERATION_FAILED;
2195 display_buffer->width = tbm_surface_get_width(buffer);
2196 display_buffer->height = tbm_surface_get_height(buffer);
2197 display_buffer->format = tbm_surface_get_format(buffer);
2198 display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
2199 count = tbm_surface_internal_get_num_planes(display_buffer->format);
2200 TDM_BACKEND_DBG("create buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d",
2201 buffer, display_buffer->width, display_buffer->height,
2202 FOURCC_STR(display_buffer->format), display_buffer->count, count);
2204 for (i = 0; i < count; i++) {
2208 bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i);
2209 bo = tbm_surface_internal_get_bo(buffer, bo_idx);
2210 display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
2212 tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
2213 &display_buffer->offsets[i],
2214 &display_buffer->pitches[i]);
2215 TDM_BACKEND_DBG(" create buffer:%p plane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)",
2216 buffer, i, display_buffer->size, display_buffer->offsets[i],
2217 display_buffer->pitches[i], bo_idx, display_buffer->handles[i]);
2220 ret = drmModeAddFB2(display_data->drm_fd, display_buffer->width, display_buffer->height,
2221 display_buffer->format, display_buffer->handles, display_buffer->pitches,
2222 display_buffer->offsets, &display_buffer->fb_id, 0);
2224 TDM_BACKEND_ERR("add fb failed: %m");
2225 free(display_buffer);
2227 *err = HAL_TDM_ERROR_OPERATION_FAILED;
2228 tbm_surface_internal_remove_destroy_handler(buffer, _tdm_vc4_display_cb_destroy_buffer, display_data);
2232 TDM_BACKEND_DBG("display_data->drm_fd : %d, display_buffer->fb_id:%u", display_data->drm_fd,
2233 display_buffer->fb_id);
2235 if (IS_RGB(display_buffer->format))
2236 display_buffer->width = display_buffer->pitches[0] >> 2;
2238 display_buffer->width = display_buffer->pitches[0];
2240 LIST_ADDTAIL(&display_buffer->link, &display_data->buffer_list);
2243 *err = HAL_TDM_ERROR_NONE;
2245 return display_buffer;
2249 tdm_vc4_display_destroy_buffer_list(tdm_vc4_display *display_data)
2251 tdm_vc4_display_buffer *b = NULL, *bb = NULL;
2253 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &display_data->buffer_list, link) {
2254 tbm_surface_internal_remove_destroy_handler(b->buffer, _tdm_vc4_display_cb_destroy_buffer, display_data);
2255 _tdm_vc4_display_cb_destroy_buffer(b->buffer, display_data);
2260 tdm_vc4_layer_set_buffer(tdm_vc4_layer *layer_data, tbm_surface_h buffer)
2262 tdm_vc4_display *display_data;
2263 tdm_vc4_display_buffer *display_buffer;
2264 hal_tdm_error err = HAL_TDM_ERROR_NONE;
2266 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2267 TDM_BACKEND_RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_INVALID_PARAMETER);
2269 TDM_BACKEND_DBG("layer_data[%p]zpos[%d] buffer:%p", layer_data, layer_data->zpos, buffer);
2271 display_data = layer_data->display_data;
2272 display_buffer = _tdm_vc4_display_find_buffer(display_data, buffer);
2273 if (!display_buffer) {
2274 display_buffer = _tdm_vc4_display_create_buffer(display_data, buffer, &err);
2275 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
2278 if (layer_data->display_buffer != display_buffer) {
2279 if (layer_data->display_buffer)
2280 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
2282 layer_data->display_buffer = display_buffer;
2283 tbm_surface_internal_ref(layer_data->display_buffer->buffer);
2284 layer_data->display_buffer_changed = 1;
2287 return HAL_TDM_ERROR_NONE;
2291 tdm_vc4_layer_unset_buffer(tdm_vc4_layer *layer_data)
2293 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2295 TDM_BACKEND_DBG("layer_data[%p]zpos[%d]", layer_data, layer_data->zpos);
2297 if (layer_data->display_buffer)
2298 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
2300 layer_data->display_buffer = NULL;
2301 layer_data->display_buffer_changed = 1;
2303 return HAL_TDM_ERROR_NONE;
2307 tdm_vc4_output_get_layer_data(tdm_vc4_output *output_data, int layer_zpos)
2309 tdm_vc4_layer *l = NULL;
2311 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, NULL);
2313 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
2314 if (l->zpos == layer_zpos)
2322 _vc4_output_data_center_rect_get(int src_w, int src_h, int dst_w, int dst_h, hal_tdm_pos *fit)
2326 if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit)
2329 rh = (float) src_h / src_w;
2334 fit->h = dst_w * rh;
2336 //TDM_BACKEND_ERR("=###### (%d, %d, %d, %d) (%f)", fit->x, fit->y, fit->w, fit->h, rh);
2340 tdm_vc4_output_prepare_mirror_commit(tdm_vc4_output *output_data, tbm_surface_h surface)
2342 tdm_vc4_layer *layer_data = NULL;
2343 tdm_vc4_layer_info info;
2344 tbm_surface_info_s surf_info;
2346 hal_tdm_pos dst_pos;
2348 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2349 TDM_BACKEND_RETURN_VAL_IF_FAIL(surface, HAL_TDM_ERROR_INVALID_PARAMETER);
2351 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->current_mode, HAL_TDM_ERROR_OPERATION_FAILED);
2353 layer_data = tdm_vc4_output_get_layer_data(output_data, 0);
2354 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_OPERATION_FAILED);
2356 memset(&dst_pos, 0, sizeof(hal_tdm_pos));
2358 tbm_surface_get_info(surface, &surf_info);
2359 // TODO: NEED to fix the calculation of the dst_pos
2360 _vc4_output_data_center_rect_get(surf_info.width, surf_info.height,
2361 output_data->current_mode->hdisplay, output_data->current_mode->hdisplay,
2364 info.src_config.size.h = surf_info.width;
2365 info.src_config.size.v = surf_info.height;
2366 info.src_config.format = TBM_FORMAT_ARGB8888;
2367 info.src_config.pos.x = 0;
2368 info.src_config.pos.y = 0;
2369 info.src_config.pos.w = surf_info.width;
2370 info.src_config.pos.h = surf_info.height;
2371 info.dst_pos.x = dst_pos.x;
2372 info.dst_pos.y = dst_pos.y;
2373 info.dst_pos.w = output_data->current_mode->hdisplay;
2374 info.dst_pos.h = output_data->current_mode->vdisplay;
2375 info.transform = HAL_TDM_TRANSFORM_NORMAL;
2377 ret = tdm_vc4_layer_set_info((tdm_vc4_layer *)layer_data, &info);
2378 TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
2380 ret = tdm_vc4_layer_set_buffer(layer_data, surface);
2381 TDM_BACKEND_RETURN_VAL_IF_FAIL(ret == HAL_TDM_ERROR_NONE, ret);
2383 return HAL_TDM_ERROR_NONE;
2387 tdm_vc4_layer_set_acquire_fence(tdm_vc4_layer *layer_data, int acquire_fence)
2389 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2391 TDM_BACKEND_DBG("layer_data[%p]zpos[%d] acquire_fence:%d", layer_data, layer_data->zpos, acquire_fence);
2393 if (layer_data->acquire_fence != acquire_fence)
2394 layer_data->acquire_fence = acquire_fence;
2396 return HAL_TDM_ERROR_NONE;