1 /**************************************************************************
5 Copyright 2015 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_drm.h"
37 static drmModeModeInfoPtr
38 _tdm_drm_display_get_mode(tdm_drm_output *output_data)
42 if (!output_data->current_mode) {
43 TDM_BACKEND_ERR("no output_data->current_mode");
47 for (i = 0; i < output_data->count_modes; i++) {
48 drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i];
49 if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) &&
50 (drm_mode->vdisplay == output_data->current_mode->vdisplay) &&
51 (drm_mode->vrefresh == output_data->current_mode->vrefresh) &&
52 (drm_mode->flags == output_data->current_mode->flags) &&
53 (drm_mode->type == output_data->current_mode->type) &&
54 !(strncmp(drm_mode->name, output_data->current_mode->name, HAL_TDM_NAME_LEN)))
62 _tdm_drm_display_to_tdm_mode(drmModeModeInfoPtr drm_mode,
63 hal_tdm_output_mode *tdm_mode)
65 tdm_mode->clock = drm_mode->clock;
66 tdm_mode->hdisplay = drm_mode->hdisplay;
67 tdm_mode->hsync_start = drm_mode->hsync_start;
68 tdm_mode->hsync_end = drm_mode->hsync_end;
69 tdm_mode->htotal = drm_mode->htotal;
70 tdm_mode->hskew = drm_mode->hskew;
71 tdm_mode->vdisplay = drm_mode->vdisplay;
72 tdm_mode->vsync_start = drm_mode->vsync_start;
73 tdm_mode->vsync_end = drm_mode->vsync_end;
74 tdm_mode->vtotal = drm_mode->vtotal;
75 tdm_mode->vscan = drm_mode->vscan;
76 tdm_mode->vrefresh = drm_mode->vrefresh;
77 tdm_mode->flags = drm_mode->flags;
78 tdm_mode->type = drm_mode->type;
79 snprintf(tdm_mode->name, HAL_TDM_NAME_LEN, "%s", drm_mode->name);
83 _tdm_drm_display_get_cur_msc(int fd, int pipe, uint *msc)
87 vbl.request.type = DRM_VBLANK_RELATIVE;
89 vbl.request.type |= DRM_VBLANK_SECONDARY;
91 vbl.request.sequence = 0;
92 if (drmWaitVBlank(fd, &vbl)) {
93 TDM_BACKEND_ERR("get vblank counter failed: %m");
95 return HAL_TDM_ERROR_OPERATION_FAILED;
98 *msc = vbl.reply.sequence;
100 return HAL_TDM_ERROR_NONE;
104 _tdm_drm_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
108 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
110 vbl.request.type |= DRM_VBLANK_SECONDARY;
112 vbl.request.sequence = *target_msc;
113 vbl.request.signal = (unsigned long)(uintptr_t)data;
115 if (drmWaitVBlank(fd, &vbl)) {
117 TDM_BACKEND_ERR("wait vblank failed: %m");
118 return HAL_TDM_ERROR_OPERATION_FAILED;
121 *target_msc = vbl.reply.sequence;
123 return HAL_TDM_ERROR_NONE;
127 _tdm_drm_output_update_status(tdm_drm_output *output_data,
128 hal_tdm_output_conn_status status)
130 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
132 if (output_data->status == status)
133 return HAL_TDM_ERROR_NONE;
135 output_data->status = status;
137 if (output_data->status_func)
138 output_data->status_func(output_data, status,
139 output_data->status_user_data);
141 return HAL_TDM_ERROR_NONE;
145 _tdm_drm_display_commit_primary_layer(tdm_drm_layer *layer_data,
146 void *user_data, int *do_waitvblank)
148 tdm_drm_display *display_data = layer_data->display_data;
149 tdm_drm_output *output_data = layer_data->output_data;
151 if (output_data->mode_changed && layer_data->display_buffer_changed) {
152 drmModeModeInfoPtr mode;
154 if (!layer_data->display_buffer) {
155 TDM_BACKEND_ERR("primary layer should have a buffer for modestting");
156 return HAL_TDM_ERROR_BAD_REQUEST;
159 output_data->mode_changed = 0;
160 layer_data->display_buffer_changed = 0;
161 layer_data->info_changed = 0;
163 mode = _tdm_drm_display_get_mode(output_data);
165 TDM_BACKEND_ERR("couldn't find proper mode");
166 return HAL_TDM_ERROR_BAD_REQUEST;
169 if (drmModeSetCrtc(display_data->drm_fd, output_data->crtc_id,
170 layer_data->display_buffer->fb_id, 0, 0,
171 &output_data->connector_id, 1, mode)) {
172 TDM_BACKEND_ERR("set crtc failed: %m");
173 return HAL_TDM_ERROR_OPERATION_FAILED;
176 _tdm_drm_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
179 return HAL_TDM_ERROR_NONE;
180 } else if (layer_data->display_buffer_changed) {
181 layer_data->display_buffer_changed = 0;
183 if (!layer_data->display_buffer) {
184 if (drmModeSetCrtc(display_data->drm_fd, output_data->crtc_id,
185 0, 0, 0, NULL, 0, NULL)) {
186 TDM_BACKEND_ERR("unset crtc failed: %m");
187 return HAL_TDM_ERROR_OPERATION_FAILED;
190 if (output_data->status == HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
191 _tdm_drm_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED);
195 tdm_drm_event_data *event_data = calloc(1, sizeof(tdm_drm_event_data));
198 TDM_BACKEND_ERR("alloc failed");
199 return HAL_TDM_ERROR_OUT_OF_MEMORY;
202 event_data->type = TDM_DRM_EVENT_TYPE_PAGEFLIP;
203 event_data->output_data = output_data;
204 event_data->user_data = user_data;
205 if (drmModePageFlip(display_data->drm_fd, output_data->crtc_id,
206 layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) {
207 TDM_BACKEND_ERR("pageflip failed: %m");
209 return HAL_TDM_ERROR_OPERATION_FAILED;
215 return HAL_TDM_ERROR_NONE;
219 _tdm_drm_display_commit_layer(tdm_drm_layer *layer_data)
221 tdm_drm_display *display_data = layer_data->display_data;
222 tdm_drm_output *output_data = layer_data->output_data;
223 uint32_t fx, fy, fw, fh;
226 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
227 return HAL_TDM_ERROR_NONE;
229 if (output_data->current_mode)
230 crtc_w = output_data->current_mode->hdisplay;
232 drmModeCrtcPtr crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id);
234 TDM_BACKEND_ERR("getting crtc failed");
235 return HAL_TDM_ERROR_OPERATION_FAILED;
237 crtc_w = crtc->width;
239 TDM_BACKEND_ERR("getting crtc width failed");
240 drmModeFreeCrtc(crtc);
241 return HAL_TDM_ERROR_OPERATION_FAILED;
243 drmModeFreeCrtc(crtc);
246 layer_data->display_buffer_changed = 0;
247 layer_data->info_changed = 0;
249 if (!layer_data->display_buffer) {
250 if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id,
251 output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
252 TDM_BACKEND_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
254 return HAL_TDM_ERROR_NONE;
257 /* Source values are 16.16 fixed point */
258 fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
259 fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
260 fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
261 fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
263 if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id,
264 output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
265 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
266 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
267 fx, fy, fw, fh) < 0) {
268 TDM_BACKEND_ERR("set plane(%d) failed: %m", layer_data->plane_id);
269 return HAL_TDM_ERROR_OPERATION_FAILED;
272 TDM_BACKEND_INFO("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
273 layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
274 layer_data->display_buffer->fb_id,
275 layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
276 layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
277 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
278 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
280 return HAL_TDM_ERROR_NONE;
284 _tdm_drm_display_cb_event(int fd, unsigned int sequence,
285 unsigned int tv_sec, unsigned int tv_usec,
288 tdm_drm_event_data *event_data = user_data;
289 tdm_drm_output *output_data;
290 tdm_drm_hwc *hwc_data;
293 TDM_BACKEND_ERR("no event data");
297 output_data = event_data->output_data;
299 switch (event_data->type) {
300 case TDM_DRM_EVENT_TYPE_PAGEFLIP:
301 hwc_data = output_data->hwc_data;
303 TDM_BACKEND_ERR("no hwc_data");
307 if (hwc_data->commit_func)
308 hwc_data->commit_func(hwc_data, sequence,
310 event_data->user_data);
312 case TDM_DRM_EVENT_TYPE_WAIT:
313 if (output_data->vblank_func)
314 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
315 event_data->user_data);
317 case TDM_DRM_EVENT_TYPE_COMMIT:
318 hwc_data = output_data->hwc_data;
320 TDM_BACKEND_ERR("no hwc_data");
324 if (hwc_data->commit_func)
325 hwc_data->commit_func(hwc_data, sequence,
327 event_data->user_data);
337 _tdm_drm_display_create_layer_list(tdm_drm_display *display_data)
339 tdm_drm_output *output_data = NULL;
342 if (LIST_IS_EMPTY(&display_data->output_list)) {
343 TDM_BACKEND_ERR("no output");
344 return HAL_TDM_ERROR_OPERATION_FAILED;
347 /* The TDM drm backend only support one output. */
348 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
352 if (display_data->plane_res->count_planes == 0) {
353 TDM_BACKEND_ERR("no layer error");
354 return HAL_TDM_ERROR_OPERATION_FAILED;
357 for (i = 0; i < display_data->plane_res->count_planes; i++) {
358 tdm_drm_layer *layer_data;
359 drmModePlanePtr plane;
361 plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]);
363 TDM_BACKEND_ERR("no plane");
367 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
368 drmModeFreePlane(plane);
372 layer_data = calloc(1, sizeof(tdm_drm_layer));
374 TDM_BACKEND_ERR("alloc failed");
375 drmModeFreePlane(plane);
379 layer_data->display_data = display_data;
380 layer_data->output_data = output_data;
381 layer_data->plane_id = display_data->plane_res->planes[i];
383 layer_data->capabilities = TDM_DRM_LAYER_CAPABILITY_PRIMARY |
384 TDM_DRM_LAYER_CAPABILITY_GRAPHIC;
385 output_data->primary_layer = layer_data;
387 TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
388 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
389 layer_data->capabilities);
391 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
393 drmModeFreePlane(plane);
395 /* can't take care of other planes for various hardware devices */
399 return HAL_TDM_ERROR_NONE;
402 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
405 _tdm_drm_display_get_property(tdm_drm_display *display_data,
406 unsigned int obj_id, unsigned int obj_type,
407 const char *name, unsigned int *value,
410 drmModeObjectPropertiesPtr props = NULL;
413 props = drmModeObjectGetProperties(display_data->drm_fd, obj_id, obj_type);
415 return HAL_TDM_ERROR_OPERATION_FAILED;
417 for (i = 0; i < props->count_props; i++) {
418 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd,
424 if (!strcmp(prop->name, name)) {
426 *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
428 *value = (unsigned int)props->prop_values[i];
429 drmModeFreeProperty(prop);
430 drmModeFreeObjectProperties(props);
431 return HAL_TDM_ERROR_NONE;
434 drmModeFreeProperty(prop);
436 drmModeFreeObjectProperties(props);
437 TDM_BACKEND_DBG("coundn't find '%s' property", name);
438 return HAL_TDM_ERROR_OPERATION_FAILED;
442 _tdm_drm_display_create_layer_list_type(tdm_drm_display *display_data)
444 tdm_drm_output *output_data = NULL;
445 drmModePlanePtr *planes = NULL;
446 unsigned int *types = NULL;
447 unsigned int type = 0;
448 int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt;
449 int opos_next, cpos_next;
453 if (LIST_IS_EMPTY(&display_data->output_list)) {
454 TDM_BACKEND_ERR("no output");
455 return HAL_TDM_ERROR_OPERATION_FAILED;
458 /* The TDM drm backend only support one output. */
459 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
463 ret = _tdm_drm_display_get_property(display_data,
464 display_data->plane_res->planes[0],
465 DRM_MODE_OBJECT_PLANE, "type", &type,
467 if (ret != HAL_TDM_ERROR_NONE) {
468 TDM_BACKEND_ERR("plane doesn't have 'type' property. Call a fallback function");
470 /* if a plane doesn't have "type" property, we call a fallback function
473 return _tdm_drm_display_create_layer_list(display_data);
476 planes = calloc(display_data->plane_res->count_planes, sizeof(drmModePlanePtr));
478 TDM_BACKEND_ERR("alloc failed");
482 types = calloc(display_data->plane_res->count_planes, sizeof(unsigned int));
484 TDM_BACKEND_ERR("alloc failed");
489 for (i = 0; i < display_data->plane_res->count_planes; i++) {
490 drmModePlanePtr plane;
492 plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]);
494 TDM_BACKEND_ERR("no plane(%d)", display_data->plane_res->planes[i]);
498 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
499 drmModeFreePlane(plane);
503 ret = _tdm_drm_display_get_property(display_data,
504 display_data->plane_res->planes[i],
505 DRM_MODE_OBJECT_PLANE, "type", &type,
507 if (ret != HAL_TDM_ERROR_NONE) {
508 drmModeFreePlane(plane);
509 TDM_BACKEND_ERR("plane(%d) doesn't have 'type' info",
510 display_data->plane_res->planes[i]);
514 /* The TDM drm backend only support a primary layer. */
515 if (type != DRM_PLANE_TYPE_PRIMARY) {
516 TDM_BACKEND_INFO("The TDM drm backend only support a primary layer. plane(%d) type(%d)",
517 plane->plane_id, type);
518 drmModeFreePlane(plane);
522 planes[plane_cnt] = plane;
523 types[plane_cnt] = type;
527 primary_cnt = ovl_cnt = cursor_cnt = 0;
528 for (i = 0; i < plane_cnt; i++) {
529 if (types[i] == DRM_PLANE_TYPE_CURSOR)
531 else if (types[i] == DRM_PLANE_TYPE_OVERLAY)
533 else if (types[i] == DRM_PLANE_TYPE_PRIMARY)
536 TDM_BACKEND_ERR("invalid type(%d)", types[i]);
539 if (primary_cnt != 1) {
540 TDM_BACKEND_ERR("primary layer count(%d) should be one", primary_cnt);
546 for (i = 0; i < plane_cnt; i++) {
547 tdm_drm_layer *layer_data;
549 layer_data = calloc(1, sizeof(tdm_drm_layer));
551 TDM_BACKEND_ERR("alloc failed");
555 layer_data->display_data = display_data;
556 layer_data->output_data = output_data;
557 layer_data->plane_id = planes[i]->plane_id;
559 if (types[i] == DRM_PLANE_TYPE_CURSOR) {
560 layer_data->capabilities = TDM_DRM_LAYER_CAPABILITY_CURSOR |
561 TDM_DRM_LAYER_CAPABILITY_GRAPHIC;
562 layer_data->zpos = cpos_next++;
563 } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
564 layer_data->capabilities = TDM_DRM_LAYER_CAPABILITY_OVERLAY |
565 TDM_DRM_LAYER_CAPABILITY_GRAPHIC;
566 layer_data->zpos = opos_next++;
567 } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
568 layer_data->capabilities = TDM_DRM_LAYER_CAPABILITY_PRIMARY |
569 TDM_DRM_LAYER_CAPABILITY_GRAPHIC;
570 layer_data->zpos = 0;
571 output_data->primary_layer = layer_data;
577 TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
578 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
579 layer_data->zpos, layer_data->capabilities);
581 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
584 for (i = 0; i < plane_cnt; i++)
586 drmModeFreePlane(planes[i]);
591 return HAL_TDM_ERROR_NONE;
595 for (i = 0; i < display_data->plane_res->count_planes; i++)
597 drmModeFreePlane(planes[i]);
603 return HAL_TDM_ERROR_OPERATION_FAILED;
608 tdm_drm_display_create_layer_list(tdm_drm_display *display_data)
610 tdm_drm_output *output_data = NULL;
613 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
614 if (display_data->has_universal_plane)
615 ret = _tdm_drm_display_create_layer_list_type(display_data);
618 ret = _tdm_drm_display_create_layer_list(display_data);
620 if (ret != HAL_TDM_ERROR_NONE)
623 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
624 if (!output_data->primary_layer) {
625 TDM_BACKEND_ERR("output(%d) no primary layer", output_data->pipe);
626 return HAL_TDM_ERROR_OPERATION_FAILED;
630 return HAL_TDM_ERROR_NONE;
634 tdm_drm_display_destroy_output_list(tdm_drm_display *display_data)
636 tdm_drm_output *o = NULL, *oo = NULL;
637 tdm_drm_hwc *hwc_data = NULL;
639 if (LIST_IS_EMPTY(&display_data->output_list))
642 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &display_data->output_list, link) {
643 hwc_data = o->hwc_data;
644 if (hwc_data && hwc_data->target_hwc_window)
645 drm_hwc_window_destroy(hwc_data->target_hwc_window);
648 if (!LIST_IS_EMPTY(&o->layer_list)) {
649 tdm_drm_layer *l = NULL, *ll = NULL;
650 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
652 if (l->display_buffer)
653 tbm_surface_internal_unref(l->display_buffer->buffer);
658 free(o->output_modes);
664 tdm_drm_display_update_output_status(tdm_drm_display *display_data)
666 tdm_drm_output *output_data = NULL;
668 if (LIST_IS_EMPTY(&display_data->output_list))
671 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
672 drmModeConnectorPtr connector;
673 hal_tdm_output_conn_status new_status;
675 connector = drmModeGetConnector(display_data->drm_fd,
676 output_data->connector_id);
678 TDM_BACKEND_ERR("no connector: %d", output_data->connector_id);
682 if (connector->connection == DRM_MODE_CONNECTED)
683 new_status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED;
685 new_status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
687 _tdm_drm_output_update_status(output_data, new_status);
689 drmModeFreeConnector(connector);
694 tdm_drm_display_create_output_list(tdm_drm_display *display_data)
696 tdm_drm_output *output_data;
700 drmModeConnectorPtr connector;
701 drmModeEncoderPtr encoder;
703 int crtc_id = 0, c, j;
705 RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&display_data->output_list),
706 HAL_TDM_ERROR_OPERATION_FAILED);
708 /* check if there is a connected output */
709 for (i = 0; i < display_data->mode_res->count_connectors; i++) {
710 connector = drmModeGetConnector(display_data->drm_fd,
711 display_data->mode_res->connectors[i]);
713 TDM_BACKEND_ERR("no connector");
714 return HAL_TDM_ERROR_OPERATION_FAILED;
717 /* The TDM drm backend considers only 1 connector because it is the TDM
718 * reference backend and can't take care of all hardware devices.
719 * To support various connectors, planes and crtcs, the new TDM backend
720 * should be implemented.
722 if (connector->connection == DRM_MODE_CONNECTED) {
724 drmModeFreeConnector(connector);
727 drmModeFreeConnector(connector);
730 /* use the first connecoct_id if there is not connector which is connected */
734 /* The TDM drm backend considers only 1 connector because it is the TDM
735 * reference backend and can't take care of all hardware devices.
736 * To support various connectors, planes and crtcs, the new TDM backend
737 * should be implemented.
739 connector = drmModeGetConnector(display_data->drm_fd,
740 display_data->mode_res->connectors[conn_idx]);
742 TDM_BACKEND_ERR("no connector");
743 ret = HAL_TDM_ERROR_OPERATION_FAILED;
747 if (connector->count_encoders != 1) {
748 TDM_BACKEND_ERR("too many encoders: %d", connector->count_encoders);
749 drmModeFreeConnector(connector);
750 ret = HAL_TDM_ERROR_OPERATION_FAILED;
754 encoder = drmModeGetEncoder(display_data->drm_fd, connector->encoders[0]);
756 TDM_BACKEND_ERR("no encoder");
757 drmModeFreeConnector(connector);
758 ret = HAL_TDM_ERROR_OPERATION_FAILED;
762 for (c = 0; c < display_data->mode_res->count_crtcs; c++) {
763 if (allocated & (1 << c))
766 if ((encoder->possible_crtcs & (1 << c)) == 0)
769 crtc_id = display_data->mode_res->crtcs[c];
770 allocated |= (1 << c);
775 TDM_BACKEND_ERR("no possible crtc");
776 drmModeFreeConnector(connector);
777 drmModeFreeEncoder(encoder);
778 ret = HAL_TDM_ERROR_OPERATION_FAILED;
782 output_data = calloc(1, sizeof(tdm_drm_output));
784 TDM_BACKEND_ERR("alloc failed");
785 drmModeFreeConnector(connector);
786 drmModeFreeEncoder(encoder);
787 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
791 LIST_INITHEAD(&output_data->layer_list);
793 output_data->display_data = display_data;
794 output_data->connector_id = display_data->mode_res->connectors[conn_idx];
795 output_data->encoder_id = encoder->encoder_id;
796 output_data->crtc_id = crtc_id;
797 output_data->pipe = c;
798 output_data->connector_type = connector->connector_type;
799 output_data->connector_type_id = connector->connector_type_id;
801 if (connector->connection == DRM_MODE_CONNECTED)
802 output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED;
804 output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
806 for (j = 0; j < connector->count_props; j++) {
807 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd,
808 connector->props[j]);
811 if (!strcmp(prop->name, "DPMS")) {
812 output_data->dpms_prop_id = connector->props[j];
813 drmModeFreeProperty(prop);
816 drmModeFreeProperty(prop);
819 if (output_data->dpms_prop_id == 0)
820 TDM_BACKEND_WRN("not support DPMS");
822 output_data->count_modes = connector->count_modes;
823 output_data->drm_modes = calloc(connector->count_modes,
824 sizeof(drmModeModeInfo));
825 if (!output_data->drm_modes) {
826 TDM_BACKEND_ERR("alloc failed");
828 drmModeFreeConnector(connector);
829 drmModeFreeEncoder(encoder);
830 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
833 output_data->output_modes = calloc(connector->count_modes,
834 sizeof(hal_tdm_output_mode));
835 if (!output_data->output_modes) {
836 TDM_BACKEND_ERR("alloc failed");
837 free(output_data->drm_modes);
839 drmModeFreeConnector(connector);
840 drmModeFreeEncoder(encoder);
841 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
844 for (j = 0; j < connector->count_modes; j++) {
845 output_data->drm_modes[j] = connector->modes[j];
846 _tdm_drm_display_to_tdm_mode(&output_data->drm_modes[j],
847 &output_data->output_modes[j]);
850 LIST_ADDTAIL(&output_data->link, &display_data->output_list);
852 TDM_BACKEND_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
853 output_data, output_data->connector_id, output_data->status,
854 output_data->connector_type,
855 output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
856 output_data->pipe, output_data->dpms_prop_id);
858 drmModeFreeEncoder(encoder);
859 drmModeFreeConnector(connector);
861 TDM_BACKEND_DBG("output count: %d", display_data->mode_res->count_connectors);
863 return HAL_TDM_ERROR_NONE;
865 tdm_drm_display_destroy_output_list(display_data);
870 drm_display_get_capability(hal_tdm_display *display, hal_tdm_caps_display *caps)
872 RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
874 caps->max_layer_count = -1; /* not defined */
876 return HAL_TDM_ERROR_NONE;
880 drm_display_get_pp_capability(hal_tdm_display *display, hal_tdm_caps_pp *caps)
882 return tdm_drm_pp_get_capability(display, caps);
886 drm_display_get_outputs(hal_tdm_display *display, int *count, hal_tdm_error *error)
888 tdm_drm_display *display_data = display;
889 tdm_drm_output *output_data = NULL;
890 hal_tdm_output **outputs;
894 RETURN_VAL_IF_FAIL(display_data, NULL);
895 RETURN_VAL_IF_FAIL(count, NULL);
898 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link)
902 ret = HAL_TDM_ERROR_NONE;
906 /* will be freed in frontend */
907 outputs = calloc(*count, sizeof(tdm_drm_output *));
909 TDM_BACKEND_ERR("failed: alloc memory");
911 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
916 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link)
917 outputs[i++] = output_data;
920 *error = HAL_TDM_ERROR_NONE;
930 drm_display_get_fd(hal_tdm_display *display, int *fd)
932 tdm_drm_display *display_data = display;
934 RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER);
935 RETURN_VAL_IF_FAIL(fd, HAL_TDM_ERROR_INVALID_PARAMETER);
937 *fd = display_data->drm_fd;
939 return HAL_TDM_ERROR_NONE;
943 drm_display_handle_events(hal_tdm_display *display)
945 tdm_drm_display *display_data = display;
948 RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER);
950 memset(&ctx, 0, sizeof(drmEventContext));
952 ctx.version = DRM_EVENT_CONTEXT_VERSION;
953 ctx.page_flip_handler = _tdm_drm_display_cb_event;
954 ctx.vblank_handler = _tdm_drm_display_cb_event;
956 drmHandleEvent(display_data->drm_fd, &ctx);
958 return HAL_TDM_ERROR_NONE;
962 drm_display_create_pp(hal_tdm_display *display, hal_tdm_error *error)
964 tdm_drm_display *display_data = display;
966 RETURN_VAL_IF_FAIL(display_data, NULL);
968 return tdm_drm_pp_create(display_data, error);
972 drm_output_get_capability(hal_tdm_output *output, hal_tdm_caps_output *caps)
974 tdm_drm_output *output_data = output;
975 tdm_drm_display *display_data;
976 drmModeConnectorPtr connector = NULL;
977 drmModeCrtcPtr crtc = NULL;
978 drmModeObjectPropertiesPtr props = NULL;
982 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
983 RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
985 memset(caps, 0, sizeof(hal_tdm_caps_output));
987 display_data = output_data->display_data;
989 snprintf(caps->maker, HAL_TDM_NAME_LEN, "unknown");
990 snprintf(caps->model, HAL_TDM_NAME_LEN, "unknown");
991 snprintf(caps->name, HAL_TDM_NAME_LEN, "unknown");
993 caps->status = output_data->status;
994 caps->type = output_data->connector_type;
995 caps->type_id = output_data->connector_type_id;
997 connector = drmModeGetConnector(display_data->drm_fd, output_data->connector_id);
998 RETURN_VAL_IF_FAIL(connector, HAL_TDM_ERROR_OPERATION_FAILED);
1000 caps->mode_count = connector->count_modes;
1001 caps->modes = calloc(1, sizeof(hal_tdm_output_mode) * caps->mode_count);
1003 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1004 TDM_BACKEND_ERR("alloc failed\n");
1007 for (i = 0; i < caps->mode_count; i++)
1008 caps->modes[i] = output_data->output_modes[i];
1010 caps->mmWidth = connector->mmWidth;
1011 caps->mmHeight = connector->mmHeight;
1012 caps->subpixel = connector->subpixel;
1014 caps->min_w = display_data->mode_res->min_width;
1015 caps->min_h = display_data->mode_res->min_height;
1016 caps->max_w = display_data->mode_res->max_width;
1017 caps->max_h = display_data->mode_res->max_height;
1018 caps->preferred_align = -1;
1020 crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id);
1022 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1023 TDM_BACKEND_ERR("get crtc failed: %m\n");
1027 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id,
1028 DRM_MODE_OBJECT_CRTC);
1030 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1031 TDM_BACKEND_ERR("get crtc properties failed: %m\n");
1035 caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props);
1037 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1038 TDM_BACKEND_ERR("alloc failed\n");
1042 caps->prop_count = 0;
1043 for (i = 0; i < props->count_props; i++) {
1044 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]);
1047 snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name);
1048 caps->props[caps->prop_count].id = props->props[i];
1050 drmModeFreeProperty(prop);
1053 caps->capabilities |= HAL_TDM_OUTPUT_CAPABILITY_HWC;
1055 drmModeFreeObjectProperties(props);
1056 drmModeFreeCrtc(crtc);
1057 drmModeFreeConnector(connector);
1059 return HAL_TDM_ERROR_NONE;
1061 drmModeFreeCrtc(crtc);
1062 drmModeFreeObjectProperties(props);
1063 drmModeFreeConnector(connector);
1066 memset(caps, 0, sizeof(hal_tdm_caps_output));
1071 drm_output_set_property(hal_tdm_output *output, unsigned int id, hal_tdm_value value)
1073 tdm_drm_output *output_data = output;
1074 tdm_drm_display *display_data;
1077 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1078 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1080 display_data = output_data->display_data;
1081 ret = drmModeObjectSetProperty(display_data->drm_fd,
1082 output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
1085 TDM_BACKEND_ERR("set property failed: %m");
1086 return HAL_TDM_ERROR_OPERATION_FAILED;
1089 return HAL_TDM_ERROR_NONE;
1093 drm_output_get_property(hal_tdm_output *output, unsigned int id, hal_tdm_value *value)
1095 tdm_drm_output *output_data = output;
1096 tdm_drm_display *display_data;
1097 drmModeObjectPropertiesPtr props;
1100 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1101 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1102 RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER);
1104 display_data = output_data->display_data;
1105 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id,
1106 DRM_MODE_OBJECT_CRTC);
1107 if (props == NULL) {
1108 TDM_BACKEND_ERR("get property failed: %m");
1109 return HAL_TDM_ERROR_OPERATION_FAILED;
1112 for (i = 0; i < props->count_props; i++)
1113 if (props->props[i] == id) {
1114 (*value).u32 = (uint)props->prop_values[i];
1118 drmModeFreeObjectProperties(props);
1120 return HAL_TDM_ERROR_NONE;
1124 drm_output_wait_vblank(hal_tdm_output *output, int interval, int sync,
1127 tdm_drm_output *output_data = output;
1128 tdm_drm_display *display_data;
1129 tdm_drm_event_data *event_data;
1133 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1135 event_data = calloc(1, sizeof(tdm_drm_event_data));
1137 TDM_BACKEND_ERR("alloc failed");
1138 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1141 display_data = output_data->display_data;
1143 ret = _tdm_drm_display_get_cur_msc(display_data->drm_fd, output_data->pipe,
1145 if (ret != HAL_TDM_ERROR_NONE)
1148 target_msc += interval;
1150 event_data->type = TDM_DRM_EVENT_TYPE_WAIT;
1151 event_data->output_data = output_data;
1152 event_data->user_data = user_data;
1154 ret = _tdm_drm_display_wait_vblank(display_data->drm_fd, output_data->pipe,
1155 &target_msc, event_data);
1156 if (ret != HAL_TDM_ERROR_NONE)
1159 return HAL_TDM_ERROR_NONE;
1166 drm_output_set_vblank_handler(hal_tdm_output *output,
1167 hal_tdm_output_vblank_handler func)
1169 tdm_drm_output *output_data = output;
1171 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1172 RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1174 output_data->vblank_func = func;
1176 return HAL_TDM_ERROR_NONE;
1180 drm_output_commit(hal_tdm_output *output, int sync, void *user_data)
1182 tdm_drm_output *output_data = output;
1183 tdm_drm_display *display_data;
1184 tdm_drm_layer *layer_data = NULL;
1186 int do_waitvblank = 1;
1188 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1190 display_data = output_data->display_data;
1192 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1193 if (layer_data == output_data->primary_layer) {
1194 ret = _tdm_drm_display_commit_primary_layer(layer_data, user_data,
1196 if (ret != HAL_TDM_ERROR_NONE)
1199 ret = _tdm_drm_display_commit_layer(layer_data);
1200 if (ret != HAL_TDM_ERROR_NONE)
1205 if (do_waitvblank == 1) {
1206 tdm_drm_event_data *event_data = calloc(1, sizeof(tdm_drm_event_data));
1210 TDM_BACKEND_ERR("alloc failed");
1211 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1214 ret = _tdm_drm_display_get_cur_msc(display_data->drm_fd, output_data->pipe,
1216 if (ret != HAL_TDM_ERROR_NONE) {
1223 event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
1224 event_data->output_data = output_data;
1225 event_data->user_data = user_data;
1227 ret = _tdm_drm_display_wait_vblank(display_data->drm_fd, output_data->pipe,
1228 &target_msc, event_data);
1229 if (ret != HAL_TDM_ERROR_NONE) {
1235 return HAL_TDM_ERROR_NONE;
1239 drm_output_set_commit_handler(hal_tdm_output *output,
1240 hal_tdm_output_commit_handler func)
1242 tdm_drm_output *output_data = output;
1244 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1245 RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1247 output_data->commit_func = func;
1249 return HAL_TDM_ERROR_NONE;
1253 drm_output_set_dpms(hal_tdm_output *output, hal_tdm_output_dpms dpms_value)
1255 tdm_drm_output *output_data = output;
1256 tdm_drm_display *display_data;
1259 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1261 if (output_data->dpms_prop_id == 0) {
1262 TDM_BACKEND_WRN("not support DPMS");
1263 return HAL_TDM_ERROR_OPERATION_FAILED;
1266 display_data = output_data->display_data;
1267 ret = drmModeObjectSetProperty(display_data->drm_fd,
1268 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1269 output_data->dpms_prop_id, dpms_value);
1271 TDM_BACKEND_ERR("set dpms failed: %m");
1272 return HAL_TDM_ERROR_OPERATION_FAILED;
1275 output_data->current_dpms = dpms_value;
1277 return HAL_TDM_ERROR_NONE;
1281 drm_output_get_dpms(hal_tdm_output *output, hal_tdm_output_dpms *dpms_value)
1283 tdm_drm_output *output_data = output;
1284 tdm_drm_display *display_data;
1285 drmModeObjectPropertiesPtr props;
1288 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1289 RETURN_VAL_IF_FAIL(dpms_value, HAL_TDM_ERROR_INVALID_PARAMETER);
1291 display_data = output_data->display_data;
1292 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->connector_id,
1293 DRM_MODE_OBJECT_CONNECTOR);
1294 if (props == NULL) {
1295 TDM_BACKEND_ERR("get property failed: %m");
1296 return HAL_TDM_ERROR_OPERATION_FAILED;
1299 for (i = 0; i < props->count_props; i++)
1300 if (props->props[i] == output_data->dpms_prop_id) {
1301 *dpms_value = (uint)props->prop_values[i];
1305 drmModeFreeObjectProperties(props);
1307 return HAL_TDM_ERROR_NONE;
1311 drm_output_set_mode(hal_tdm_output *output, const hal_tdm_output_mode *mode)
1313 tdm_drm_output *output_data = output;
1314 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1316 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1317 RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER);
1319 /* create or replace the target_window when the output mode is set */
1320 ret = drm_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
1321 if (ret != HAL_TDM_ERROR_NONE) {
1322 TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret);
1326 output_data->current_mode = mode;
1327 output_data->mode_changed = 1;
1329 return HAL_TDM_ERROR_NONE;
1333 drm_output_get_mode(hal_tdm_output *output, const hal_tdm_output_mode **mode)
1335 tdm_drm_output *output_data = output;
1337 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1338 RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER);
1340 *mode = output_data->current_mode;
1342 return HAL_TDM_ERROR_NONE;
1346 drm_output_get_hwc(hal_tdm_output *output, hal_tdm_error *error)
1348 tdm_drm_hwc *hwc_data = NULL;
1349 tdm_drm_output *output_data = output;
1350 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1353 TDM_BACKEND_ERR("invalid params");
1355 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
1359 if (output_data->hwc_data) {
1360 TDM_BACKEND_INFO("hwc_data already exists");
1362 *error = HAL_TDM_ERROR_NONE;
1363 return output_data->hwc_data;
1366 hwc_data = calloc(1, sizeof(tdm_drm_hwc));
1368 TDM_BACKEND_ERR("alloc failed");
1370 *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
1373 hwc_data->output_data = output_data;
1375 LIST_INITHEAD(&hwc_data->hwc_window_list);
1377 output_data->hwc_data = hwc_data;
1379 ret = drm_hwc_initailize_target_window(output_data->hwc_data);
1380 if (ret != HAL_TDM_ERROR_NONE) {
1381 TDM_BACKEND_ERR("create target hwc window failed (%d)", ret);
1389 *error = HAL_TDM_ERROR_NONE;
1395 drm_output_set_status_handler(hal_tdm_output *output,
1396 hal_tdm_output_status_handler func,
1399 tdm_drm_output *output_data = output;
1401 RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1402 RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1404 output_data->status_func = func;
1405 output_data->status_user_data = user_data;
1407 return HAL_TDM_ERROR_NONE;
1411 drm_layer_get_capability(tdm_drm_layer *layer, tdm_drm_caps_layer *caps)
1413 tdm_drm_layer *layer_data = layer;
1414 tdm_drm_display *display_data;
1415 drmModePlanePtr plane = NULL;
1416 drmModeObjectPropertiesPtr props = NULL;
1417 int i, format_count = 0;
1420 RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1421 RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
1423 memset(caps, 0, sizeof(tdm_drm_caps_layer));
1425 display_data = layer_data->display_data;
1426 plane = drmModeGetPlane(display_data->drm_fd, layer_data->plane_id);
1428 TDM_BACKEND_ERR("get plane failed: %m");
1429 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1433 caps->capabilities = layer_data->capabilities;
1434 caps->zpos = layer_data->zpos; /* if VIDEO layer, zpos is -1 */
1436 caps->format_count = plane->count_formats;
1437 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1438 if (!caps->formats) {
1439 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1440 TDM_BACKEND_ERR("alloc failed\n");
1444 for (i = 0; i < caps->format_count; i++) {
1445 /* TODO: kernel reports wrong formats */
1446 if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
1447 plane->formats[i] != DRM_FORMAT_ARGB8888) {
1448 TDM_BACKEND_WRN("plane(%d) zpos(%d) %c%c%c%c skipped",
1449 layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i]));
1452 caps->formats[format_count] = tdm_drm_format_to_tbm_format(plane->formats[i]);
1456 caps->format_count = format_count;
1458 props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id,
1459 DRM_MODE_OBJECT_PLANE);
1461 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1462 TDM_BACKEND_ERR("get plane properties failed: %m\n");
1466 caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props);
1468 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1469 TDM_BACKEND_ERR("alloc failed\n");
1473 caps->prop_count = 0;
1474 for (i = 0; i < props->count_props; i++) {
1475 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]);
1478 if (!strncmp(prop->name, "type", HAL_TDM_NAME_LEN)) {
1479 drmModeFreeProperty(prop);
1482 if (!strncmp(prop->name, "zpos", HAL_TDM_NAME_LEN)) {
1483 drmModeFreeProperty(prop);
1486 snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name);
1487 caps->props[caps->prop_count].id = props->props[i];
1489 drmModeFreeProperty(prop);
1492 drmModeFreeObjectProperties(props);
1493 drmModeFreePlane(plane);
1495 return HAL_TDM_ERROR_NONE;
1497 drmModeFreeObjectProperties(props);
1498 drmModeFreePlane(plane);
1499 free(caps->formats);
1501 memset(caps, 0, sizeof(tdm_drm_caps_layer));
1506 drm_layer_set_property(tdm_drm_layer *layer, unsigned int id, hal_tdm_value value)
1508 tdm_drm_layer *layer_data = layer;
1509 tdm_drm_display *display_data;
1512 RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1513 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1515 display_data = layer_data->display_data;
1516 ret = drmModeObjectSetProperty(display_data->drm_fd,
1517 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
1520 TDM_BACKEND_ERR("set property failed: %m");
1521 return HAL_TDM_ERROR_OPERATION_FAILED;
1524 return HAL_TDM_ERROR_NONE;
1528 drm_layer_get_property(tdm_drm_layer *layer, unsigned int id, hal_tdm_value *value)
1530 tdm_drm_layer *layer_data = layer;
1531 tdm_drm_display *display_data;
1532 drmModeObjectPropertiesPtr props;
1535 RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1536 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1537 RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER);
1539 display_data = layer_data->display_data;
1540 props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id,
1541 DRM_MODE_OBJECT_PLANE);
1542 if (props == NULL) {
1543 TDM_BACKEND_ERR("get property failed: %m");
1544 return HAL_TDM_ERROR_OPERATION_FAILED;
1547 for (i = 0; i < props->count_props; i++)
1548 if (props->props[i] == id) {
1549 (*value).u32 = (uint)props->prop_values[i];
1553 drmModeFreeObjectProperties(props);
1555 return HAL_TDM_ERROR_NONE;
1559 drm_layer_set_info(tdm_drm_layer *layer, tdm_drm_layer_info *info)
1561 tdm_drm_layer *layer_data = layer;
1563 RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1564 RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
1566 layer_data->info = *info;
1567 layer_data->info_changed = 1;
1569 return HAL_TDM_ERROR_NONE;
1573 drm_layer_get_info(tdm_drm_layer *layer, tdm_drm_layer_info *info)
1575 tdm_drm_layer *layer_data = layer;
1577 RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1578 RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
1580 *info = layer_data->info;
1582 return HAL_TDM_ERROR_NONE;
1585 static tdm_drm_display_buffer *
1586 _tdm_drm_display_find_buffer(tdm_drm_display *display_data, tbm_surface_h buffer)
1588 tdm_drm_display_buffer *display_buffer = NULL;
1590 LIST_FOR_EACH_ENTRY(display_buffer, &display_data->buffer_list, link) {
1591 if (display_buffer->buffer == buffer)
1592 return display_buffer;
1599 _tdm_drm_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
1601 tdm_drm_display *display_data;
1602 tdm_drm_display_buffer *display_buffer;
1603 tdm_drm_layer *layer_data = NULL;
1604 tdm_drm_output *output_data = NULL;
1605 char buf[256] = {0,};
1609 TDM_BACKEND_ERR("no user_data");
1613 TDM_BACKEND_ERR("no buffer");
1617 display_data = (tdm_drm_display *) user_data;
1619 display_buffer = _tdm_drm_display_find_buffer(display_data, buffer);
1620 if (!display_buffer) {
1621 TDM_BACKEND_ERR("no display_buffer");
1625 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
1626 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1627 if (display_buffer == layer_data->display_buffer)
1628 layer_data->display_buffer = NULL;
1632 if (display_buffer->fb_id > 0) {
1633 if (drmModeRmFB(display_data->drm_fd, display_buffer->fb_id) < 0) {
1634 ret_tmp = strerror_r(errno, buf, sizeof(buf));
1635 TDM_BACKEND_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
1639 TDM_BACKEND_DBG("destroy buffer:%p", display_buffer->buffer);
1641 LIST_DEL(&display_buffer->link);
1642 free(display_buffer);
1645 static tdm_drm_display_buffer *
1646 _tdm_drm_display_create_buffer(tdm_drm_display *display_data, tbm_surface_h buffer, hal_tdm_error *err)
1648 tdm_drm_display_buffer *display_buffer = NULL;
1651 display_buffer = calloc(1, sizeof(tdm_drm_display_buffer));
1652 if (!display_buffer) {
1653 TDM_BACKEND_ERR("alloc failed");
1655 *err = HAL_TDM_ERROR_OUT_OF_MEMORY;
1659 display_buffer->buffer = buffer;
1661 ret = tbm_surface_internal_add_destroy_handler(buffer, _tdm_drm_display_cb_destroy_buffer, display_data);
1663 TDM_BACKEND_ERR("add destroy handler fail");
1664 free(display_buffer);
1666 *err = HAL_TDM_ERROR_OPERATION_FAILED;
1670 display_buffer->width = tbm_surface_get_width(buffer);
1671 display_buffer->height = tbm_surface_get_height(buffer);
1672 display_buffer->format = tbm_surface_get_format(buffer);
1673 display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
1674 count = tbm_surface_internal_get_num_planes(display_buffer->format);
1675 TDM_BACKEND_DBG("create buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d",
1676 buffer, display_buffer->width, display_buffer->height,
1677 FOURCC_STR(display_buffer->format), display_buffer->count, count);
1679 for (i = 0; i < count; i++) {
1683 bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i);
1684 bo = tbm_surface_internal_get_bo(buffer, bo_idx);
1685 display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
1687 tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
1688 &display_buffer->offsets[i],
1689 &display_buffer->pitches[i]);
1690 TDM_BACKEND_DBG(" create buffer:%p plane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)",
1691 buffer, i, display_buffer->size, display_buffer->offsets[i],
1692 display_buffer->pitches[i], bo_idx, display_buffer->handles[i]);
1695 ret = drmModeAddFB2(display_data->drm_fd, display_buffer->width, display_buffer->height,
1696 display_buffer->format, display_buffer->handles, display_buffer->pitches,
1697 display_buffer->offsets, &display_buffer->fb_id, 0);
1699 TDM_BACKEND_ERR("add fb failed: %m");
1700 free(display_buffer);
1702 *err = HAL_TDM_ERROR_OPERATION_FAILED;
1703 tbm_surface_internal_remove_destroy_handler(buffer, _tdm_drm_display_cb_destroy_buffer, display_data);
1707 TDM_BACKEND_DBG("display_data->drm_fd : %d, display_buffer->fb_id:%u", display_data->drm_fd,
1708 display_buffer->fb_id);
1710 if (IS_RGB(display_buffer->format))
1711 display_buffer->width = display_buffer->pitches[0] >> 2;
1713 display_buffer->width = display_buffer->pitches[0];
1715 LIST_ADDTAIL(&display_buffer->link, &display_data->buffer_list);
1718 *err = HAL_TDM_ERROR_NONE;
1720 return display_buffer;
1724 _hal_tdm_display_destroy_buffer_list(tdm_drm_display *display_data)
1726 tdm_drm_display_buffer *b = NULL, *bb = NULL;
1728 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &display_data->buffer_list, link) {
1729 tbm_surface_internal_remove_destroy_handler(b->buffer, _tdm_drm_display_cb_destroy_buffer, display_data);
1730 _tdm_drm_display_cb_destroy_buffer(b->buffer, display_data);
1735 drm_layer_set_buffer(tdm_drm_layer *layer, tbm_surface_h buffer)
1737 tdm_drm_layer *layer_data = layer;
1738 tdm_drm_display *display_data;
1739 tdm_drm_display_buffer *display_buffer;
1740 hal_tdm_error err = HAL_TDM_ERROR_NONE;
1742 RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1743 RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_INVALID_PARAMETER);
1745 TDM_BACKEND_DBG("layer[%p]zpos[%d] buffer:%p", layer, layer_data->zpos, buffer);
1747 display_data = layer_data->display_data;
1748 display_buffer = _tdm_drm_display_find_buffer(display_data, buffer);
1749 if (!display_buffer) {
1750 display_buffer = _tdm_drm_display_create_buffer(display_data, buffer, &err);
1751 RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
1754 if (layer_data->display_buffer != display_buffer) {
1755 if (layer_data->display_buffer)
1756 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
1758 layer_data->display_buffer = display_buffer;
1759 tbm_surface_internal_ref(layer_data->display_buffer->buffer);
1760 layer_data->display_buffer_changed = 1;
1763 return HAL_TDM_ERROR_NONE;
1767 drm_layer_unset_buffer(tdm_drm_layer *layer)
1769 tdm_drm_layer *layer_data = layer;
1771 RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1773 if (!(layer_data->capabilities & TDM_DRM_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) {
1774 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
1775 layer_data->display_buffer = NULL;
1778 layer_data->display_buffer_changed = 1;
1780 return HAL_TDM_ERROR_NONE;
1784 drm_output_data_get_layer_data(tdm_drm_output *output_data, int layer_zpos)
1786 tdm_drm_layer *l = NULL;
1788 RETURN_VAL_IF_FAIL(output_data, NULL);
1790 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
1791 if (l->zpos == layer_zpos)