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_nexell.h"
39 static drmModeModeInfoPtr
40 _tdm_nexell_display_get_mode(tdm_nexell_output *output_data)
44 if (!output_data->current_mode) {
45 TDM_BACKEND_ERR("no output_data->current_mode");
49 for (i = 0; i < output_data->count_modes; i++) {
50 drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i];
51 if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) &&
52 (drm_mode->vdisplay == output_data->current_mode->vdisplay) &&
53 (drm_mode->vrefresh == output_data->current_mode->vrefresh) &&
54 (drm_mode->flags == output_data->current_mode->flags) &&
55 (drm_mode->type == output_data->current_mode->type) &&
56 !(strncmp(drm_mode->name, output_data->current_mode->name, HAL_TDM_NAME_LEN)))
64 _tdm_nexell_display_to_tdm_mode(drmModeModeInfoPtr drm_mode,
65 hal_tdm_output_mode *tdm_mode)
67 tdm_mode->clock = drm_mode->clock;
68 tdm_mode->hdisplay = drm_mode->hdisplay;
69 tdm_mode->hsync_start = drm_mode->hsync_start;
70 tdm_mode->hsync_end = drm_mode->hsync_end;
71 tdm_mode->htotal = drm_mode->htotal;
72 tdm_mode->hskew = drm_mode->hskew;
73 tdm_mode->vdisplay = drm_mode->vdisplay;
74 tdm_mode->vsync_start = drm_mode->vsync_start;
75 tdm_mode->vsync_end = drm_mode->vsync_end;
76 tdm_mode->vtotal = drm_mode->vtotal;
77 tdm_mode->vscan = drm_mode->vscan;
78 tdm_mode->vrefresh = drm_mode->vrefresh;
79 tdm_mode->flags = drm_mode->flags;
80 tdm_mode->type = drm_mode->type;
81 snprintf(tdm_mode->name, HAL_TDM_NAME_LEN, "%s", drm_mode->name);
85 _tdm_nexell_display_get_cur_msc (int fd, int pipe, uint *msc)
89 vbl.request.type = DRM_VBLANK_RELATIVE;
91 vbl.request.type |= DRM_VBLANK_SECONDARY;
93 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
95 vbl.request.sequence = 0;
96 if (drmWaitVBlank(fd, &vbl)) {
97 TDM_BACKEND_ERR("get vblank counter failed: %m");
99 return HAL_TDM_ERROR_OPERATION_FAILED;
102 *msc = vbl.reply.sequence;
104 return HAL_TDM_ERROR_NONE;
108 _tdm_nexell_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
112 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
114 vbl.request.type |= DRM_VBLANK_SECONDARY;
116 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
118 vbl.request.sequence = *target_msc;
119 vbl.request.signal = (unsigned long)(uintptr_t)data;
121 if (drmWaitVBlank(fd, &vbl)) {
122 TDM_BACKEND_ERR("wait vblank failed: %m");
124 return HAL_TDM_ERROR_OPERATION_FAILED;
127 *target_msc = vbl.reply.sequence;
129 return HAL_TDM_ERROR_NONE;
133 _tdm_nexell_output_update_status(tdm_nexell_output *output_data,
134 hal_tdm_output_conn_status status)
136 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
138 if (output_data->status == status)
139 return HAL_TDM_ERROR_NONE;
141 output_data->status = status;
143 if (output_data->status_func)
144 output_data->status_func(output_data, status,
145 output_data->status_user_data);
147 return HAL_TDM_ERROR_NONE;
151 _tdm_nexell_display_commit_primary_layer(tdm_nexell_layer *layer_data,
152 void *user_data, int *do_waitvblank)
154 tdm_nexell_display *display_data = layer_data->display_data;
155 tdm_nexell_output *output_data = layer_data->output_data;
157 if (output_data->mode_changed && layer_data->display_buffer_changed) {
158 drmModeModeInfoPtr mode;
160 if (!layer_data->display_buffer) {
161 TDM_BACKEND_ERR("primary layer_data should have a buffer for modestting");
162 return HAL_TDM_ERROR_BAD_REQUEST;
165 output_data->mode_changed = 0;
166 layer_data->display_buffer_changed = 0;
167 layer_data->info_changed = 0;
169 mode = _tdm_nexell_display_get_mode(output_data);
171 TDM_BACKEND_ERR("couldn't find proper mode");
172 return HAL_TDM_ERROR_BAD_REQUEST;
175 if (drmModeSetCrtc(display_data->drm_fd, output_data->crtc_id,
176 layer_data->display_buffer->fb_id, 0, 0,
177 &output_data->connector_id, 1, mode)) {
178 TDM_BACKEND_ERR("set crtc failed: %m");
179 return HAL_TDM_ERROR_OPERATION_FAILED;
182 _tdm_nexell_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
185 return HAL_TDM_ERROR_NONE;
186 } else if (layer_data->display_buffer_changed) {
187 layer_data->display_buffer_changed = 0;
189 if (layer_data->display_buffer) {
190 tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
193 TDM_BACKEND_ERR("alloc failed");
194 return HAL_TDM_ERROR_OUT_OF_MEMORY;
197 event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT;
198 event_data->output_data = output_data;
199 event_data->user_data = user_data;
200 if (drmModePageFlip(display_data->drm_fd, output_data->crtc_id,
201 layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) {
202 TDM_BACKEND_ERR("pageflip failed: %m");
204 return HAL_TDM_ERROR_OPERATION_FAILED;
209 /* to call a user commit handler whenever committed */
213 return HAL_TDM_ERROR_NONE;
217 _tdm_nexell_display_commit_layer(tdm_nexell_layer *layer_data)
219 tdm_nexell_display *display_data = layer_data->display_data;
220 tdm_nexell_output *output_data = layer_data->output_data;
221 uint32_t fx, fy, fw, fh;
224 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
225 return HAL_TDM_ERROR_NONE;
227 if (output_data->current_mode)
228 crtc_w = output_data->current_mode->hdisplay;
230 drmModeCrtcPtr crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id);
232 TDM_BACKEND_ERR("getting crtc failed");
233 return HAL_TDM_ERROR_OPERATION_FAILED;
235 crtc_w = crtc->width;
237 TDM_BACKEND_ERR("getting crtc width failed");
238 drmModeFreeCrtc(crtc);
239 return HAL_TDM_ERROR_OPERATION_FAILED;
241 drmModeFreeCrtc(crtc);
244 // reset the changed flags
245 layer_data->display_buffer_changed = 0;
246 layer_data->info_changed = 0;
248 if (layer_data->display_buffer) { // set plane
249 /* Source values are 16.16 fixed point */
250 fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
251 fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
252 fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
253 fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
255 TDM_BACKEND_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
256 layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
257 layer_data->display_buffer->fb_id,
258 layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
259 layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
260 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
261 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
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;
271 } else { // unset plane
272 TDM_BACKEND_DBG("plane(%d) crtc(%d) pos(%d) : unset plane\n",
273 layer_data->plane_id, output_data->crtc_id, layer_data->zpos);
275 if (drmModeSetPlane(display_data->drm_fd, layer_data->plane_id,
276 output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
277 TDM_BACKEND_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
280 return HAL_TDM_ERROR_NONE;
284 _tdm_nexell_display_cb_event(int fd, unsigned int sequence,
285 unsigned int tv_sec, unsigned int tv_usec,
288 tdm_nexell_event_data *event_data = user_data;
289 tdm_nexell_output *output_data;
290 tdm_nexell_hwc *hwc_data;
293 TDM_BACKEND_ERR("no event data");
297 output_data = event_data->output_data;
299 switch (event_data->type) {
300 case HAL_TDM_NEXELL_EVENT_TYPE_PAGEFLIP:
301 if (output_data->commit_func)
302 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
303 event_data->user_data);
305 case HAL_TDM_NEXELL_EVENT_TYPE_WAIT:
306 if (output_data->vblank_func)
307 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
308 event_data->user_data);
310 case HAL_TDM_NEXELL_EVENT_TYPE_COMMIT:
311 hwc_data = output_data->hwc_data;
313 TDM_BACKEND_ERR("no hwc_data");
317 if (hwc_data->commit_func)
318 hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec,
319 event_data->user_data);
329 _tdm_nexell_display_create_layer_list(tdm_nexell_display *display_data)
331 tdm_nexell_output *output_data = NULL;
334 if (LIST_IS_EMPTY(&display_data->output_list)) {
335 TDM_BACKEND_ERR("no output");
336 return HAL_TDM_ERROR_OPERATION_FAILED;
339 /* The TDM drm backend only support one output. */
340 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
344 if (display_data->plane_res->count_planes == 0) {
345 TDM_BACKEND_ERR("no layer_data error");
346 return HAL_TDM_ERROR_OPERATION_FAILED;
349 for (i = 0; i < display_data->plane_res->count_planes; i++) {
350 tdm_nexell_layer *layer_data;
351 drmModePlanePtr plane;
353 plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]);
355 TDM_BACKEND_ERR("no plane");
359 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
360 drmModeFreePlane(plane);
364 layer_data = calloc(1, sizeof(tdm_nexell_layer));
366 TDM_BACKEND_ERR("alloc failed");
367 drmModeFreePlane(plane);
371 layer_data->display_data = display_data;
372 layer_data->output_data = output_data;
373 layer_data->plane_id = display_data->plane_res->planes[i];
375 layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_PRIMARY |
376 TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC;
377 output_data->primary_layer = layer_data;
379 TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
380 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
381 layer_data->capabilities);
383 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
385 drmModeFreePlane(plane);
387 /* can't take care of other planes for various hardware devices */
391 return HAL_TDM_ERROR_NONE;
394 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
397 _tdm_nexell_display_get_property(tdm_nexell_display *display_data,
398 unsigned int obj_id, unsigned int obj_type,
399 const char *name, unsigned int *value,
402 drmModeObjectPropertiesPtr props = NULL;
405 props = drmModeObjectGetProperties(display_data->drm_fd, obj_id, obj_type);
407 return HAL_TDM_ERROR_OPERATION_FAILED;
409 for (i = 0; i < props->count_props; i++) {
410 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd,
416 if (!strcmp(prop->name, name)) {
418 *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
420 *value = (unsigned int)props->prop_values[i];
421 drmModeFreeProperty(prop);
422 drmModeFreeObjectProperties(props);
423 return HAL_TDM_ERROR_NONE;
426 drmModeFreeProperty(prop);
428 drmModeFreeObjectProperties(props);
429 TDM_BACKEND_DBG("coundn't find '%s' property", name);
430 return HAL_TDM_ERROR_OPERATION_FAILED;
434 _nexell_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id)
436 drmModeObjectPropertiesPtr properties = NULL;
437 drmModePropertyPtr property = NULL;
440 properties = drmModeObjectGetProperties(drm_fd, object_id, object_type);
441 if (properties == NULL) {
442 TDM_BACKEND_ERR("drmModeObjectGetProperties failed");
443 return HAL_TDM_ERROR_OPERATION_FAILED;
446 for (i = 0; i < properties->count_props; i++) {
447 property = drmModeGetProperty(drm_fd, properties->props[i]);
448 if (property == NULL) {
452 if (strcmp(property->name, name) == 0) {
453 *id = property->prop_id;
454 drmModeFreeProperty(property);
457 drmModeFreeProperty(property);
460 drmModeFreeObjectProperties(properties);
462 return HAL_TDM_ERROR_NONE;
466 _tdm_nexell_display_create_layer_list_type(tdm_nexell_display *display_data)
468 tdm_nexell_output *output_data = NULL;
469 drmModePlanePtr *planes = NULL;
470 unsigned int *types = NULL;
471 unsigned int type = 0;
472 int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt;
473 int opos_next, cpos_next;
477 if (LIST_IS_EMPTY(&display_data->output_list)) {
478 TDM_BACKEND_ERR("no output");
479 return HAL_TDM_ERROR_OPERATION_FAILED;
482 /* The TDM drm backend only support one output. */
483 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
487 ret = _tdm_nexell_display_get_property(display_data,
488 display_data->plane_res->planes[0],
489 DRM_MODE_OBJECT_PLANE, "type", &type,
491 if (ret != HAL_TDM_ERROR_NONE) {
492 TDM_BACKEND_ERR("plane doesn't have 'type' property. Call a fallback function");
494 /* if a plane doesn't have "type" property, we call a fallback function
497 return _tdm_nexell_display_create_layer_list(display_data);
500 planes = calloc(display_data->plane_res->count_planes, sizeof(drmModePlanePtr));
502 TDM_BACKEND_ERR("alloc failed");
506 types = calloc(display_data->plane_res->count_planes, sizeof(unsigned int));
508 TDM_BACKEND_ERR("alloc failed");
513 for (i = 0; i < display_data->plane_res->count_planes; i++) {
514 drmModePlanePtr plane;
516 plane = drmModeGetPlane(display_data->drm_fd, display_data->plane_res->planes[i]);
518 TDM_BACKEND_ERR("no plane(%d)", display_data->plane_res->planes[i]);
522 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
523 drmModeFreePlane(plane);
527 ret = _tdm_nexell_display_get_property(display_data,
528 display_data->plane_res->planes[i],
529 DRM_MODE_OBJECT_PLANE, "type", &type,
531 if (ret != HAL_TDM_ERROR_NONE) {
532 drmModeFreePlane(plane);
533 TDM_BACKEND_ERR("plane(%d) doesn't have 'type' info",
534 display_data->plane_res->planes[i]);
538 planes[plane_cnt] = plane;
539 types[plane_cnt] = type;
543 primary_cnt = ovl_cnt = cursor_cnt = 0;
544 for (i = 0; i < plane_cnt; i++) {
545 if (types[i] == DRM_PLANE_TYPE_CURSOR)
547 else if (types[i] == DRM_PLANE_TYPE_OVERLAY)
549 else if (types[i] == DRM_PLANE_TYPE_PRIMARY)
552 TDM_BACKEND_ERR("invalid type(%d)", types[i]);
555 if (primary_cnt != 1) {
556 TDM_BACKEND_ERR("primary layer_data count(%d) should be one", primary_cnt);
563 TDM_BACKEND_ERR("plane count(%d) should be over 1", plane_cnt);
567 for (i = plane_cnt - 1; i >= 0; i--) {
568 tdm_nexell_layer *layer_data;
570 layer_data = calloc(1, sizeof(tdm_nexell_layer));
572 TDM_BACKEND_ERR("alloc failed");
576 layer_data->display_data = display_data;
577 layer_data->output_data = output_data;
578 layer_data->plane_id = planes[i]->plane_id;
580 if (types[i] == DRM_PLANE_TYPE_CURSOR) {
581 layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_CURSOR |
582 TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC |
583 TDM_NEXELL_LAYER_CAPABILITY_SCANOUT;
584 layer_data->zpos = cpos_next++;
585 TDM_BACKEND_INFO("layer_data(%p): cursor zpos(%d)", layer_data, layer_data->zpos);
586 } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
587 if (opos_next == 0) {
588 layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_OVERLAY |
589 TDM_NEXELL_LAYER_CAPABILITY_SCALE |
590 TDM_NEXELL_LAYER_CAPABILITY_SCANOUT;
592 layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_OVERLAY |
593 TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC |
594 TDM_NEXELL_LAYER_CAPABILITY_RESEVED_MEMORY |
595 TDM_NEXELL_LAYER_CAPABILITY_SCANOUT;
597 if (opos_next == 1) {
598 layer_data->zpos = 2;
601 layer_data->zpos = opos_next++;
604 TDM_BACKEND_INFO("layer_data(%p): overlay zpos(%d)", layer_data, layer_data->zpos);
605 } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
606 layer_data->capabilities = TDM_NEXELL_LAYER_CAPABILITY_PRIMARY |
607 TDM_NEXELL_LAYER_CAPABILITY_GRAPHIC |
608 TDM_NEXELL_LAYER_CAPABILITY_RESEVED_MEMORY |
609 TDM_NEXELL_LAYER_CAPABILITY_SCANOUT;
610 layer_data->zpos = 1;
611 output_data->primary_layer = layer_data;
613 TDM_BACKEND_INFO("layer_data(%p): primary zpos(%d)", layer_data, layer_data->zpos);
619 TDM_BACKEND_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
620 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
621 layer_data->zpos, layer_data->capabilities);
623 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
625 /* get the atomic prop ids*/
626 if (display_data->has_atomic) {
627 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
628 DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id);
629 if (ret != HAL_TDM_ERROR_NONE) {
634 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
635 DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id);
636 if (ret != HAL_TDM_ERROR_NONE) {
641 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
642 DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x);
643 if (ret != HAL_TDM_ERROR_NONE) {
648 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
649 DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y);
650 if (ret != HAL_TDM_ERROR_NONE) {
655 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
656 DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w);
657 if (ret != HAL_TDM_ERROR_NONE) {
662 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
663 DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h);
664 if (ret != HAL_TDM_ERROR_NONE) {
669 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
670 DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x);
671 if (ret != HAL_TDM_ERROR_NONE) {
676 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
677 DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y);
678 if (ret != HAL_TDM_ERROR_NONE) {
683 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
684 DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w);
685 if (ret != HAL_TDM_ERROR_NONE) {
690 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, layer_data->plane_id,
691 DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h);
692 if (ret != HAL_TDM_ERROR_NONE) {
699 for (i = 0; i < plane_cnt; i++)
701 drmModeFreePlane(planes[i]);
706 return HAL_TDM_ERROR_NONE;
710 for (i = 0; i < display_data->plane_res->count_planes; i++)
712 drmModeFreePlane(planes[i]);
718 return HAL_TDM_ERROR_OPERATION_FAILED;
723 tdm_nexell_display_create_layer_list(tdm_nexell_display *display_data)
725 tdm_nexell_output *output_data = NULL;
728 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
729 if (display_data->has_universal_plane)
730 ret = _tdm_nexell_display_create_layer_list_type(display_data);
733 ret = _tdm_nexell_display_create_layer_list(display_data);
735 if (ret != HAL_TDM_ERROR_NONE)
738 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
739 if (!output_data->primary_layer) {
740 TDM_BACKEND_ERR("output(%d) no primary layer_data", output_data->pipe);
741 return HAL_TDM_ERROR_OPERATION_FAILED;
745 return HAL_TDM_ERROR_NONE;
749 tdm_nexell_display_destroy_output_list(tdm_nexell_display *display_data)
751 tdm_nexell_output *o = NULL, *oo = NULL;
752 tdm_nexell_hwc *hwc_data = NULL;
754 if (LIST_IS_EMPTY(&display_data->output_list))
757 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &display_data->output_list, link) {
758 hwc_data = o->hwc_data;
759 if (hwc_data && hwc_data->target_hwc_window)
760 nexell_hwc_window_destroy(hwc_data->target_hwc_window);
763 if (!LIST_IS_EMPTY(&o->layer_list)) {
764 tdm_nexell_layer *l = NULL, *ll = NULL;
765 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
767 if (l->display_buffer)
768 tbm_surface_internal_unref(l->display_buffer->buffer);
773 free(o->output_modes);
779 tdm_nexell_display_update_output_status(tdm_nexell_display *display_data)
781 tdm_nexell_output *output_data = NULL;
783 if (LIST_IS_EMPTY(&display_data->output_list))
786 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
787 drmModeConnectorPtr connector;
788 hal_tdm_output_conn_status new_status;
790 connector = drmModeGetConnector(display_data->drm_fd,
791 output_data->connector_id);
793 TDM_BACKEND_ERR("no connector: %d", output_data->connector_id);
797 if (connector->connection == DRM_MODE_CONNECTED)
798 new_status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED;
800 new_status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
802 _tdm_nexell_output_update_status(output_data, new_status);
804 drmModeFreeConnector(connector);
809 tdm_nexell_display_create_output_list(tdm_nexell_display *display_data)
811 tdm_nexell_output *output_data;
815 drmModeConnectorPtr connector;
816 drmModeEncoderPtr encoder;
818 int hdmia_idx = -1, hdmib_idx = -1;
819 int crtc_id = 0, c, j;
821 TDM_BACKEND_RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&display_data->output_list),
822 HAL_TDM_ERROR_OPERATION_FAILED);
824 /* check if there is a connected output */
825 for (i = 0; i < display_data->mode_res->count_connectors; i++) {
826 connector = drmModeGetConnector(display_data->drm_fd,
827 display_data->mode_res->connectors[i]);
829 TDM_BACKEND_ERR("no connector");
830 return HAL_TDM_ERROR_OPERATION_FAILED;
833 /* The TDM drm backend considers only 1 connector because it is the TDM
834 * reference backend and can't take care of all hardware devices.
835 * To support various connectors, planes and crtcs, the new TDM backend
836 * should be implemented.
838 if (connector->connection == DRM_MODE_CONNECTED) {
840 drmModeFreeConnector(connector);
844 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
846 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
849 drmModeFreeConnector(connector);
852 /* use the hdmi connector if there is no connected connector. */
853 /* if there is no hdmi connector, use first connector. */
854 if (conn_idx == -1) {
856 conn_idx = hdmia_idx;
857 else if (hdmib_idx != -1)
858 conn_idx = hdmib_idx;
863 /* The TDM drm backend considers only 1 connector because it is the TDM
864 * reference backend and can't take care of all hardware devices.
865 * To support various connectors, planes and crtcs, the new TDM backend
866 * should be implemented.
868 connector = drmModeGetConnector(display_data->drm_fd,
869 display_data->mode_res->connectors[conn_idx]);
871 TDM_BACKEND_ERR("no connector");
872 ret = HAL_TDM_ERROR_OPERATION_FAILED;
876 if (connector->count_encoders != 1) {
877 TDM_BACKEND_ERR("too many encoders: %d", connector->count_encoders);
878 drmModeFreeConnector(connector);
879 ret = HAL_TDM_ERROR_OPERATION_FAILED;
883 encoder = drmModeGetEncoder(display_data->drm_fd, connector->encoders[0]);
885 TDM_BACKEND_ERR("no encoder");
886 drmModeFreeConnector(connector);
887 ret = HAL_TDM_ERROR_OPERATION_FAILED;
891 for (c = 0; c < display_data->mode_res->count_crtcs; c++) {
892 if ((encoder->possible_crtcs & (1 << c)) == 0)
895 crtc_id = display_data->mode_res->crtcs[c];
896 allocated |= (1 << c);
901 TDM_BACKEND_ERR("no possible crtc");
902 drmModeFreeConnector(connector);
903 drmModeFreeEncoder(encoder);
904 ret = HAL_TDM_ERROR_OPERATION_FAILED;
908 output_data = calloc(1, sizeof(tdm_nexell_output));
910 TDM_BACKEND_ERR("alloc failed");
911 drmModeFreeConnector(connector);
912 drmModeFreeEncoder(encoder);
913 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
917 LIST_INITHEAD(&output_data->layer_list);
919 output_data->display_data = display_data;
920 output_data->connector_id = display_data->mode_res->connectors[conn_idx];
921 output_data->encoder_id = encoder->encoder_id;
922 output_data->crtc_id = crtc_id;
923 output_data->pipe = c;
924 output_data->connector_type = connector->connector_type;
925 output_data->connector_type_id = connector->connector_type_id;
927 if (connector->connection == DRM_MODE_CONNECTED)
928 output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_CONNECTED;
930 output_data->status = HAL_TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
932 for (j = 0; j < connector->count_props; j++) {
933 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd,
934 connector->props[j]);
937 if (!strcmp(prop->name, "DPMS")) {
938 output_data->dpms_prop_id = connector->props[j];
939 drmModeFreeProperty(prop);
942 drmModeFreeProperty(prop);
945 if (output_data->dpms_prop_id == 0)
946 TDM_BACKEND_WRN("not support DPMS");
948 output_data->count_modes = connector->count_modes;
949 output_data->drm_modes = calloc(connector->count_modes,
950 sizeof(drmModeModeInfo));
951 if (!output_data->drm_modes) {
952 TDM_BACKEND_ERR("alloc failed");
954 drmModeFreeConnector(connector);
955 drmModeFreeEncoder(encoder);
956 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
959 output_data->output_modes = calloc(connector->count_modes,
960 sizeof(hal_tdm_output_mode));
961 if (!output_data->output_modes) {
962 TDM_BACKEND_ERR("alloc failed");
963 free(output_data->drm_modes);
965 drmModeFreeConnector(connector);
966 drmModeFreeEncoder(encoder);
967 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
970 for (j = 0; j < connector->count_modes; j++) {
971 output_data->drm_modes[j] = connector->modes[j];
972 _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[j],
973 &output_data->output_modes[j]);
976 LIST_ADDTAIL(&output_data->link, &display_data->output_list);
978 TDM_BACKEND_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
979 output_data, output_data->connector_id, output_data->status,
980 output_data->connector_type,
981 output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
982 output_data->pipe, output_data->dpms_prop_id);
984 drmModeFreeEncoder(encoder);
985 drmModeFreeConnector(connector);
987 /* get the atomic prop ids*/
988 if (display_data->has_atomic) {
989 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->connector_id,
990 DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id);
991 if (ret != HAL_TDM_ERROR_NONE)
994 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id,
995 DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id);
996 if (ret != HAL_TDM_ERROR_NONE)
999 ret = _nexell_output_get_atomic_prop_id(display_data->drm_fd, output_data->crtc_id,
1000 DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active);
1001 if (ret != HAL_TDM_ERROR_NONE)
1005 TDM_BACKEND_DBG("output count: %d", display_data->mode_res->count_connectors);
1007 return HAL_TDM_ERROR_NONE;
1009 tdm_nexell_display_destroy_output_list(display_data);
1014 nexell_display_get_capability(hal_tdm_display *display, hal_tdm_caps_display *caps)
1016 TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
1018 caps->max_layer_count = -1; /* not defined */
1020 return HAL_TDM_ERROR_NONE;
1024 nexell_display_get_pp_capability(hal_tdm_display *display, hal_tdm_caps_pp *caps)
1026 return tdm_nexell_pp_get_capability(display, caps);
1030 nexell_display_get_outputs(hal_tdm_display *display, int *count, hal_tdm_error *error)
1032 tdm_nexell_display *display_data = display;
1033 tdm_nexell_output *output_data = NULL;
1034 hal_tdm_output **outputs;
1038 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, NULL);
1039 TDM_BACKEND_RETURN_VAL_IF_FAIL(count, NULL);
1042 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link)
1046 ret = HAL_TDM_ERROR_NONE;
1050 /* will be freed in frontend */
1051 outputs = calloc(*count, sizeof(tdm_nexell_output *));
1053 TDM_BACKEND_ERR("failed: alloc memory");
1055 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1060 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link)
1061 outputs[i++] = output_data;
1064 *error = HAL_TDM_ERROR_NONE;
1074 nexell_display_get_fd(hal_tdm_display *display, int *fd)
1076 tdm_nexell_display *display_data = display;
1078 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1079 TDM_BACKEND_RETURN_VAL_IF_FAIL(fd, HAL_TDM_ERROR_INVALID_PARAMETER);
1081 *fd = display_data->drm_fd;
1083 return HAL_TDM_ERROR_NONE;
1087 nexell_display_handle_events(hal_tdm_display *display)
1089 tdm_nexell_display *display_data = display;
1090 drmEventContext ctx;
1092 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1094 memset(&ctx, 0, sizeof(drmEventContext));
1096 ctx.version = DRM_EVENT_CONTEXT_VERSION;
1097 ctx.page_flip_handler = _tdm_nexell_display_cb_event;
1098 ctx.vblank_handler = _tdm_nexell_display_cb_event;
1100 drmHandleEvent(display_data->drm_fd, &ctx);
1102 return HAL_TDM_ERROR_NONE;
1106 nexell_display_create_pp(hal_tdm_display *display, hal_tdm_error *error)
1108 tdm_nexell_display *display_data = display;
1110 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data, NULL);
1112 return tdm_nexell_pp_create(display_data, error);
1116 nexell_output_get_capability(hal_tdm_output *output, hal_tdm_caps_output *caps)
1118 tdm_nexell_output *output_data = output;
1119 tdm_nexell_display *display_data;
1120 drmModeConnectorPtr connector = NULL;
1121 drmModeCrtcPtr crtc = NULL;
1122 drmModeObjectPropertiesPtr props = NULL;
1126 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1127 TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
1129 memset(caps, 0, sizeof(hal_tdm_caps_output));
1131 display_data = output_data->display_data;
1133 snprintf(caps->maker, HAL_TDM_NAME_LEN, "unknown");
1134 snprintf(caps->model, HAL_TDM_NAME_LEN, "unknown");
1135 snprintf(caps->name, HAL_TDM_NAME_LEN, "unknown");
1137 caps->status = output_data->status;
1138 caps->type = output_data->connector_type;
1139 caps->type_id = output_data->connector_type_id;
1141 connector = drmModeGetConnector(display_data->drm_fd, output_data->connector_id);
1142 TDM_BACKEND_RETURN_VAL_IF_FAIL(connector, HAL_TDM_ERROR_OPERATION_FAILED);
1144 caps->mode_count = connector->count_modes;
1145 caps->modes = calloc(1, sizeof(hal_tdm_output_mode) * caps->mode_count);
1147 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1148 TDM_BACKEND_ERR("alloc failed\n");
1152 if (caps->mode_count != output_data->count_modes) {
1153 drmModeModeInfoPtr new_drm_modes;
1154 hal_tdm_output_mode *new_output_modes;
1156 new_drm_modes = calloc(connector->count_modes,
1157 sizeof(drmModeModeInfo));
1158 if (!new_drm_modes) {
1159 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1160 TDM_BACKEND_ERR("alloc failed drm_modes\n");
1163 new_output_modes = calloc(connector->count_modes,
1164 sizeof(hal_tdm_output_mode));
1165 if (!new_output_modes) {
1166 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1167 TDM_BACKEND_ERR("alloc failed output_modes\n");
1168 free(new_drm_modes);
1171 free(output_data->drm_modes);
1172 free(output_data->output_modes);
1174 output_data->drm_modes = new_drm_modes;
1175 output_data->output_modes = new_output_modes;
1176 output_data->count_modes = caps->mode_count;
1179 for (i = 0; i < caps->mode_count; i++) {
1180 output_data->drm_modes[i] = connector->modes[i];
1181 _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[i],
1182 &output_data->output_modes[i]);
1183 caps->modes[i] = output_data->output_modes[i];
1186 caps->mmWidth = connector->mmWidth;
1187 caps->mmHeight = connector->mmHeight;
1188 caps->subpixel = connector->subpixel;
1190 caps->min_w = display_data->mode_res->min_width;
1191 caps->min_h = display_data->mode_res->min_height;
1192 caps->max_w = display_data->mode_res->max_width;
1193 caps->max_h = display_data->mode_res->max_height;
1194 caps->preferred_align = -1;
1196 crtc = drmModeGetCrtc(display_data->drm_fd, output_data->crtc_id);
1198 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1199 TDM_BACKEND_ERR("get crtc failed: %m\n");
1203 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id,
1204 DRM_MODE_OBJECT_CRTC);
1206 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1207 TDM_BACKEND_ERR("get crtc properties failed: %m\n");
1211 caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props);
1213 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1214 TDM_BACKEND_ERR("alloc failed\n");
1218 caps->prop_count = 0;
1219 for (i = 0; i < props->count_props; i++) {
1220 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]);
1223 snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name);
1224 caps->props[caps->prop_count].id = props->props[i];
1226 drmModeFreeProperty(prop);
1229 caps->capabilities |= HAL_TDM_OUTPUT_CAPABILITY_HWC;
1231 drmModeFreeObjectProperties(props);
1232 drmModeFreeCrtc(crtc);
1233 drmModeFreeConnector(connector);
1235 return HAL_TDM_ERROR_NONE;
1237 drmModeFreeCrtc(crtc);
1238 drmModeFreeObjectProperties(props);
1239 drmModeFreeConnector(connector);
1242 memset(caps, 0, sizeof(hal_tdm_caps_output));
1247 nexell_output_set_property(hal_tdm_output *output, unsigned int id, hal_tdm_value value)
1249 tdm_nexell_output *output_data = output;
1250 tdm_nexell_display *display_data;
1253 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1254 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1256 display_data = output_data->display_data;
1257 ret = drmModeObjectSetProperty(display_data->drm_fd,
1258 output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
1261 TDM_BACKEND_ERR("set property failed: %m");
1262 return HAL_TDM_ERROR_OPERATION_FAILED;
1265 return HAL_TDM_ERROR_NONE;
1269 nexell_output_get_property(hal_tdm_output *output, unsigned int id, hal_tdm_value *value)
1271 tdm_nexell_output *output_data = output;
1272 tdm_nexell_display *display_data;
1273 drmModeObjectPropertiesPtr props;
1276 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1277 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1278 TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER);
1280 display_data = output_data->display_data;
1281 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->crtc_id,
1282 DRM_MODE_OBJECT_CRTC);
1283 if (props == NULL) {
1284 TDM_BACKEND_ERR("get property failed: %m");
1285 return HAL_TDM_ERROR_OPERATION_FAILED;
1288 for (i = 0; i < props->count_props; i++)
1289 if (props->props[i] == id) {
1290 (*value).u32 = (uint)props->prop_values[i];
1294 drmModeFreeObjectProperties(props);
1296 return HAL_TDM_ERROR_NONE;
1300 nexell_output_wait_vblank(hal_tdm_output *output, int interval, int sync,
1303 tdm_nexell_output *output_data = output;
1304 tdm_nexell_display *display_data;
1305 tdm_nexell_event_data *event_data;
1309 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1311 event_data = calloc(1, sizeof(tdm_nexell_event_data));
1313 TDM_BACKEND_ERR("alloc failed");
1314 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1317 display_data = output_data->display_data;
1319 ret = _tdm_nexell_display_get_cur_msc(display_data->drm_fd, output_data->pipe,
1321 if (ret != HAL_TDM_ERROR_NONE)
1324 target_msc += interval;
1326 event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_WAIT;
1327 event_data->output_data = output_data;
1328 event_data->user_data = user_data;
1330 ret = _tdm_nexell_display_wait_vblank(display_data->drm_fd, output_data->pipe,
1331 &target_msc, event_data);
1332 if (ret != HAL_TDM_ERROR_NONE)
1335 return HAL_TDM_ERROR_NONE;
1342 nexell_output_set_vblank_handler(hal_tdm_output *output,
1343 hal_tdm_output_vblank_handler func)
1345 tdm_nexell_output *output_data = output;
1347 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1348 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1350 output_data->vblank_func = func;
1352 return HAL_TDM_ERROR_NONE;
1355 static hal_tdm_error
1356 _nexell_layer_add_atomic_properties(tdm_nexell_layer *layer_data, drmModeAtomicReqPtr request,
1357 uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
1358 uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h)
1360 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1362 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id);
1364 TDM_BACKEND_ERR("fail to add the atomic prop. fb_id(%u)", fb_id);
1365 return HAL_TDM_ERROR_OPERATION_FAILED;
1368 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id);
1370 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id);
1371 return HAL_TDM_ERROR_OPERATION_FAILED;
1374 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x);
1376 TDM_BACKEND_ERR("fail to add the atomic prop. src_x(%u)", src_x);
1377 return HAL_TDM_ERROR_OPERATION_FAILED;
1380 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y);
1382 TDM_BACKEND_ERR("fail to add the atomic prop. src_y(%u)", src_y);
1383 return HAL_TDM_ERROR_OPERATION_FAILED;
1386 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w);
1388 TDM_BACKEND_ERR("fail to add the atomic prop. src_w(%u)", src_w);
1389 return HAL_TDM_ERROR_OPERATION_FAILED;
1392 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h);
1394 TDM_BACKEND_ERR("fail to add the atomic prop. src_h(%u)", src_h);
1395 return HAL_TDM_ERROR_OPERATION_FAILED;
1398 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x);
1400 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x);
1401 return HAL_TDM_ERROR_OPERATION_FAILED;
1404 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y);
1406 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y);
1407 return HAL_TDM_ERROR_OPERATION_FAILED;
1410 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w);
1412 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w);
1413 return HAL_TDM_ERROR_OPERATION_FAILED;
1416 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h);
1418 TDM_BACKEND_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h);
1419 return HAL_TDM_ERROR_OPERATION_FAILED;
1422 return HAL_TDM_ERROR_NONE;
1425 static hal_tdm_error
1426 _nexell_layer_make_atomic_request(tdm_nexell_layer *layer_data, drmModeAtomicReqPtr request)
1428 tdm_nexell_display *display_data = layer_data->display_data;
1429 tdm_nexell_output *output_data = layer_data->output_data;
1430 uint32_t fx, fy, fw, fh;
1431 tdm_nexell_layer_info layer_info = layer_data->info;
1432 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1434 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
1435 return HAL_TDM_ERROR_NONE;
1437 layer_data->display_buffer_changed = 0;
1438 layer_data->info_changed = 0;
1440 if (!layer_data->display_buffer) {
1441 TDM_BACKEND_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off",
1442 display_data->drm_fd, layer_data->plane_id, output_data->crtc_id);
1444 ret = _nexell_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1445 if (ret != HAL_TDM_ERROR_NONE) {
1446 TDM_BACKEND_ERR("_nexell_layer_add_atomic_properties failed.");
1450 return HAL_TDM_ERROR_NONE;
1453 /* Source values are 16.16 fixed point */
1454 fx = ((unsigned int)layer_info.src_config.pos.x) << 16;
1455 fy = ((unsigned int)layer_info.src_config.pos.y) << 16;
1456 fw = ((unsigned int)layer_info.src_config.pos.w) << 16;
1457 fh = ((unsigned int)layer_info.src_config.pos.h) << 16;
1459 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)",
1460 display_data->drm_fd, layer_data->plane_id, layer_data->zpos,
1461 output_data->crtc_id, layer_data->display_buffer->fb_id,
1462 layer_info.src_config.pos.x, layer_info.src_config.pos.y,
1463 layer_info.src_config.pos.w, layer_info.src_config.pos.h,
1464 layer_info.dst_pos.x, layer_info.dst_pos.y,
1465 layer_info.dst_pos.w, layer_info.dst_pos.h);
1467 ret = _nexell_layer_add_atomic_properties(layer_data, request,
1468 layer_data->display_buffer->fb_id, output_data->crtc_id,
1470 layer_info.dst_pos.x, layer_info.dst_pos.y,
1471 layer_info.dst_pos.w, layer_info.dst_pos.h);
1472 if (ret != HAL_TDM_ERROR_NONE) {
1473 TDM_BACKEND_ERR("MakeAtomicRequest failed");
1477 return HAL_TDM_ERROR_NONE;
1480 static hal_tdm_error
1481 _nexell_output_atomic_commit(hal_tdm_output *output, int sync, void *user_data)
1483 tdm_nexell_output *output_data = output;
1484 tdm_nexell_layer *layer_data = NULL;
1485 tdm_nexell_event_data *event_data;
1486 drmModeAtomicReqPtr request;
1490 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1492 if (!output_data->crtc_enabled || output_data->mode_changed) {
1493 drmModeModeInfoPtr mode;
1495 layer_data = output_data->primary_layer;
1496 if (!layer_data->display_buffer) {
1497 TDM_BACKEND_ERR("primary layer_data should have a buffer for modestting");
1498 return HAL_TDM_ERROR_BAD_REQUEST;
1501 mode = _tdm_nexell_display_get_mode(output_data);
1503 TDM_BACKEND_ERR("couldn't find proper mode");
1504 return HAL_TDM_ERROR_BAD_REQUEST;
1507 if (drmModeSetCrtc(output_data->display_data->drm_fd, output_data->crtc_id,
1508 layer_data->display_buffer->fb_id, 0, 0,
1509 &output_data->connector_id, 1, mode)) {
1510 TDM_BACKEND_ERR("set crtc failed: %m");
1511 return HAL_TDM_ERROR_OPERATION_FAILED;
1514 _tdm_nexell_output_update_status(output_data, HAL_TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
1516 output_data->crtc_enabled = 1;
1517 output_data->mode_changed = 0;
1520 request = drmModeAtomicAlloc();
1522 TDM_BACKEND_ERR("drmModeAtomicAlloc failed.");
1523 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1526 flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
1528 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1529 ret = _nexell_layer_make_atomic_request(layer_data, request);
1530 if (ret != HAL_TDM_ERROR_NONE) {
1531 TDM_BACKEND_ERR("_nexell_layer_make_atomic_request failed.");
1532 drmModeAtomicFree(request);
1537 event_data = calloc(1, sizeof(tdm_nexell_event_data));
1539 TDM_BACKEND_ERR("fail to alloc event_data.");
1540 drmModeAtomicFree(request);
1541 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1544 event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT;
1545 event_data->output_data = output_data;
1546 event_data->user_data = user_data;
1548 TDM_BACKEND_DBG("==== Atomic Commit pipe, %u, crtc_id, %u connector_id, %u",
1549 output_data->pipe, output_data->crtc_id, output_data->connector_id);
1551 if (drmModeAtomicCommit(output_data->display_data->drm_fd, request, flags, event_data) < 0) {
1552 TDM_BACKEND_ERR("drmModeAtomicCommit failed.");
1554 drmModeAtomicFree(request);
1555 return HAL_TDM_ERROR_OPERATION_FAILED;
1558 drmModeAtomicFree(request);
1560 return HAL_TDM_ERROR_NONE;
1563 static hal_tdm_error
1564 _nexell_output_layers_commit(hal_tdm_output *output, int sync, void *user_data)
1566 tdm_nexell_output *output_data = output;
1567 tdm_nexell_display *display_data;
1568 tdm_nexell_layer *layer_data = NULL;
1570 int do_waitvblank = 1;
1572 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1574 display_data = output_data->display_data;
1576 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1577 if (layer_data == output_data->primary_layer) {
1578 ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data,
1580 if (ret != HAL_TDM_ERROR_NONE)
1583 ret = _tdm_nexell_display_commit_layer(layer_data);
1584 if (ret != HAL_TDM_ERROR_NONE)
1589 if (do_waitvblank == 1) {
1590 tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
1594 TDM_BACKEND_ERR("alloc failed");
1595 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1598 ret = _tdm_nexell_display_get_cur_msc(display_data->drm_fd, output_data->pipe,
1600 if (ret != HAL_TDM_ERROR_NONE) {
1607 event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT;
1608 event_data->output_data = output_data;
1609 event_data->user_data = user_data;
1611 ret = _tdm_nexell_display_wait_vblank(display_data->drm_fd, output_data->pipe,
1612 &target_msc, event_data);
1613 if (ret != HAL_TDM_ERROR_NONE) {
1619 return HAL_TDM_ERROR_NONE;
1623 nexell_output_commit(hal_tdm_output *output, int sync, void *user_data)
1625 tdm_nexell_output *output_data = output;
1626 tdm_nexell_display *display_data;
1629 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1631 display_data = output_data->display_data;
1633 /* check the atomic pageflip */
1634 if (display_data->has_atomic) {
1635 ret = _nexell_output_atomic_commit(output, sync, user_data);
1636 if (ret != HAL_TDM_ERROR_NONE) {
1637 TDM_BACKEND_ERR("_nexell_output_atomic_commit failed.");
1641 ret = _nexell_output_layers_commit(output, sync, user_data);
1642 if (ret != HAL_TDM_ERROR_NONE) {
1643 TDM_BACKEND_ERR("_nexell_output_layers_commit failed.");
1648 return HAL_TDM_ERROR_NONE;
1652 nexell_output_set_commit_handler(hal_tdm_output *output,
1653 hal_tdm_output_commit_handler func)
1655 tdm_nexell_output *output_data = output;
1657 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1658 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1660 output_data->commit_func = func;
1662 return HAL_TDM_ERROR_NONE;
1666 nexell_output_set_dpms(hal_tdm_output *output, hal_tdm_output_dpms dpms_value)
1668 tdm_nexell_output *output_data = output;
1669 tdm_nexell_display *display_data;
1672 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1674 if (output_data->dpms_prop_id == 0) {
1675 TDM_BACKEND_WRN("not support DPMS");
1676 return HAL_TDM_ERROR_OPERATION_FAILED;
1679 display_data = output_data->display_data;
1680 ret = drmModeObjectSetProperty(display_data->drm_fd,
1681 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1682 output_data->dpms_prop_id, dpms_value);
1684 TDM_BACKEND_ERR("set dpms failed: %m");
1685 return HAL_TDM_ERROR_OPERATION_FAILED;
1688 return HAL_TDM_ERROR_NONE;
1692 nexell_output_get_dpms(hal_tdm_output *output, hal_tdm_output_dpms *dpms_value)
1694 tdm_nexell_output *output_data = output;
1695 tdm_nexell_display *display_data;
1696 drmModeObjectPropertiesPtr props;
1699 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1700 TDM_BACKEND_RETURN_VAL_IF_FAIL(dpms_value, HAL_TDM_ERROR_INVALID_PARAMETER);
1702 display_data = output_data->display_data;
1703 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->connector_id,
1704 DRM_MODE_OBJECT_CONNECTOR);
1705 if (props == NULL) {
1706 TDM_BACKEND_ERR("get property failed: %m");
1707 return HAL_TDM_ERROR_OPERATION_FAILED;
1710 for (i = 0; i < props->count_props; i++)
1711 if (props->props[i] == output_data->dpms_prop_id) {
1712 *dpms_value = (uint)props->prop_values[i];
1716 drmModeFreeObjectProperties(props);
1718 return HAL_TDM_ERROR_NONE;
1722 nexell_output_set_mode(hal_tdm_output *output, const hal_tdm_output_mode *mode)
1724 tdm_nexell_output *output_data = output;
1725 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1727 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1728 TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER);
1730 /* create or replace the target_window when the output mode is set */
1731 ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
1732 if (ret != HAL_TDM_ERROR_NONE) {
1733 TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret);
1737 output_data->current_mode = mode;
1738 output_data->mode_changed = 1;
1740 TDM_BACKEND_INFO("Set the output mode: %s, %d, %d, %d, %d, %d",
1741 mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
1743 return HAL_TDM_ERROR_NONE;
1747 nexell_output_get_mode(hal_tdm_output *output, const hal_tdm_output_mode **mode)
1749 tdm_nexell_output *output_data = output;
1751 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1752 TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER);
1754 *mode = output_data->current_mode;
1756 return HAL_TDM_ERROR_NONE;
1760 nexell_output_get_hwc(hal_tdm_output *output, hal_tdm_error *error)
1762 tdm_nexell_hwc *hwc_data = NULL;
1763 tdm_nexell_output *output_data = output;
1764 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1768 TDM_BACKEND_ERR("invalid params");
1770 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
1774 if (output_data->hwc_data) {
1775 TDM_BACKEND_INFO("hwc_data already exists");
1777 *error = HAL_TDM_ERROR_NONE;
1778 return output_data->hwc_data;
1781 hwc_data = calloc(1, sizeof(tdm_nexell_hwc));
1783 TDM_BACKEND_ERR("alloc failed");
1785 *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
1789 for (i = 0; i < NUM_LAYERS; i++) {
1790 hwc_data->ui_buffer_queue[i].tqueue = NULL;
1791 hwc_data->ui_buffer_queue[i].ref_cnt = 0;
1794 hwc_data->output_data = output_data;
1796 LIST_INITHEAD(&hwc_data->hwc_window_list);
1798 output_data->hwc_data = hwc_data;
1800 ret = tdm_nexell_hwc_initailize_target_window(output_data->hwc_data);
1801 if (ret != HAL_TDM_ERROR_NONE) {
1802 TDM_BACKEND_ERR("create target hwc window failed (%d)", ret);
1810 *error = HAL_TDM_ERROR_NONE;
1816 nexell_output_set_status_handler(hal_tdm_output *output,
1817 hal_tdm_output_status_handler func,
1820 tdm_nexell_output *output_data = output;
1822 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1823 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1825 output_data->status_func = func;
1826 output_data->status_user_data = user_data;
1828 return HAL_TDM_ERROR_NONE;
1832 nexell_layer_get_capability(tdm_nexell_layer *layer_data, tdm_nexell_caps_layer *caps)
1834 tdm_nexell_display *display_data;
1835 drmModePlanePtr plane = NULL;
1836 drmModeObjectPropertiesPtr props = NULL;
1837 int i, format_count = 0;
1840 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1841 TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
1843 memset(caps, 0, sizeof(tdm_nexell_caps_layer));
1845 display_data = layer_data->display_data;
1846 plane = drmModeGetPlane(display_data->drm_fd, layer_data->plane_id);
1848 TDM_BACKEND_ERR("get plane failed: %m");
1849 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1853 caps->capabilities = layer_data->capabilities;
1854 caps->zpos = layer_data->zpos; /* if VIDEO layer_data, zpos is -1 */
1856 caps->format_count = plane->count_formats;
1857 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1858 if (!caps->formats) {
1859 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1860 TDM_BACKEND_ERR("alloc failed\n");
1864 for (i = 0; i < caps->format_count; i++) {
1865 /* TODO: kernel reports wrong formats */
1866 if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
1867 plane->formats[i] != DRM_FORMAT_ARGB8888 &&
1868 plane->formats[i] != DRM_FORMAT_YUV420) {
1869 TDM_BACKEND_WRN("plane(%d) zpos(%d) %c%c%c%c skipped",
1870 layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i]));
1873 caps->formats[format_count] = tdm_nexell_format_to_tbm_format(plane->formats[i]);
1877 caps->format_count = format_count;
1879 props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id,
1880 DRM_MODE_OBJECT_PLANE);
1882 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1883 TDM_BACKEND_ERR("get plane properties failed: %m\n");
1887 caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props);
1889 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1890 TDM_BACKEND_ERR("alloc failed\n");
1894 caps->prop_count = 0;
1895 for (i = 0; i < props->count_props; i++) {
1896 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]);
1899 if (!strncmp(prop->name, "type", HAL_TDM_NAME_LEN)) {
1900 drmModeFreeProperty(prop);
1903 if (!strncmp(prop->name, "zpos", HAL_TDM_NAME_LEN)) {
1904 drmModeFreeProperty(prop);
1907 snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name);
1908 caps->props[caps->prop_count].id = props->props[i];
1910 drmModeFreeProperty(prop);
1913 drmModeFreeObjectProperties(props);
1914 drmModeFreePlane(plane);
1916 return HAL_TDM_ERROR_NONE;
1918 drmModeFreeObjectProperties(props);
1919 drmModeFreePlane(plane);
1920 free(caps->formats);
1922 memset(caps, 0, sizeof(tdm_nexell_caps_layer));
1927 nexell_layer_set_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value value)
1929 tdm_nexell_display *display_data;
1932 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1933 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1935 display_data = layer_data->display_data;
1936 ret = drmModeObjectSetProperty(display_data->drm_fd,
1937 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
1940 TDM_BACKEND_ERR("set property failed: %m");
1941 return HAL_TDM_ERROR_OPERATION_FAILED;
1944 return HAL_TDM_ERROR_NONE;
1948 nexell_layer_get_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value *value)
1950 tdm_nexell_display *display_data;
1951 drmModeObjectPropertiesPtr props;
1954 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1955 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1956 TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER);
1958 display_data = layer_data->display_data;
1959 props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id,
1960 DRM_MODE_OBJECT_PLANE);
1961 if (props == NULL) {
1962 TDM_BACKEND_ERR("get property failed: %m");
1963 return HAL_TDM_ERROR_OPERATION_FAILED;
1966 for (i = 0; i < props->count_props; i++)
1967 if (props->props[i] == id) {
1968 (*value).u32 = (uint)props->prop_values[i];
1972 drmModeFreeObjectProperties(props);
1974 return HAL_TDM_ERROR_NONE;
1978 nexell_layer_set_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info)
1980 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1981 TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
1983 layer_data->info = *info;
1984 layer_data->info_changed = 1;
1986 return HAL_TDM_ERROR_NONE;
1990 nexell_layer_get_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info)
1992 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1993 TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
1995 *info = layer_data->info;
1997 return HAL_TDM_ERROR_NONE;
2000 static tdm_nexell_display_buffer *
2001 _tdm_nexell_display_find_buffer(tdm_nexell_display *display_data, tbm_surface_h buffer)
2003 tdm_nexell_display_buffer *display_buffer = NULL;
2005 LIST_FOR_EACH_ENTRY(display_buffer, &display_data->buffer_list, link) {
2006 if (display_buffer->buffer == buffer)
2007 return display_buffer;
2014 _tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
2016 tdm_nexell_display *display_data;
2017 tdm_nexell_display_buffer *display_buffer;
2018 tdm_nexell_layer *layer_data = NULL;
2019 tdm_nexell_output *output_data = NULL;
2020 char buf[256] = {0,};
2024 TDM_BACKEND_ERR("no user_data");
2028 TDM_BACKEND_ERR("no buffer");
2032 display_data = (tdm_nexell_display *) user_data;
2034 display_buffer = _tdm_nexell_display_find_buffer(display_data, buffer);
2035 if (!display_buffer) {
2036 TDM_BACKEND_ERR("no display_buffer");
2040 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
2041 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
2042 if (display_buffer == layer_data->display_buffer)
2043 layer_data->display_buffer = NULL;
2047 if (display_buffer->fb_id > 0) {
2048 if (drmModeRmFB(display_data->drm_fd, display_buffer->fb_id) < 0) {
2049 ret_tmp = strerror_r(errno, buf, sizeof(buf));
2050 TDM_BACKEND_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
2054 TDM_BACKEND_DBG("destroy buffer:%p", display_buffer->buffer);
2056 LIST_DEL(&display_buffer->link);
2057 free(display_buffer);
2060 static tdm_nexell_display_buffer *
2061 _tdm_nexell_display_create_buffer(tdm_nexell_display *display_data, tbm_surface_h buffer, hal_tdm_error *err)
2063 tdm_nexell_display_buffer *display_buffer = NULL;
2066 display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer));
2067 if (!display_buffer) {
2068 TDM_BACKEND_ERR("alloc failed");
2070 *err = HAL_TDM_ERROR_OUT_OF_MEMORY;
2074 display_buffer->buffer = buffer;
2076 ret = tbm_surface_internal_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, display_data);
2078 TDM_BACKEND_ERR("add destroy handler fail");
2079 free(display_buffer);
2081 *err = HAL_TDM_ERROR_OPERATION_FAILED;
2085 display_buffer->width = tbm_surface_get_width(buffer);
2086 display_buffer->height = tbm_surface_get_height(buffer);
2087 display_buffer->format = tbm_surface_get_format(buffer);
2088 display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
2089 count = tbm_surface_internal_get_num_planes(display_buffer->format);
2090 TDM_BACKEND_DBG(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d",
2091 buffer, display_buffer->width, display_buffer->height,
2092 FOURCC_STR(display_buffer->format), display_buffer->count, count);
2094 for (i = 0; i < count; i++) {
2098 bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i);
2099 bo = tbm_surface_internal_get_bo(buffer, bo_idx);
2100 display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
2102 tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
2103 &display_buffer->offsets[i],
2104 &display_buffer->pitches[i]);
2105 TDM_BACKEND_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)",
2106 i, display_buffer->size, display_buffer->offsets[i],
2107 display_buffer->pitches[i], bo_idx, display_buffer->handles[i]);
2110 ret = drmModeAddFB2(display_data->drm_fd, display_buffer->width, display_buffer->height,
2111 display_buffer->format, display_buffer->handles, display_buffer->pitches,
2112 display_buffer->offsets, &display_buffer->fb_id, 0);
2114 TDM_BACKEND_ERR("add fb failed: %m");
2115 free(display_buffer);
2117 *err = HAL_TDM_ERROR_OPERATION_FAILED;
2118 tbm_surface_internal_remove_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, display_data);
2122 TDM_BACKEND_DBG("display_data->drm_fd : %d, display_buffer->fb_id:%u", display_data->drm_fd,
2123 display_buffer->fb_id);
2125 if (IS_RGB(display_buffer->format))
2126 display_buffer->width = display_buffer->pitches[0] >> 2;
2128 display_buffer->width = display_buffer->pitches[0];
2130 LIST_ADDTAIL(&display_buffer->link, &display_data->buffer_list);
2133 *err = HAL_TDM_ERROR_NONE;
2135 return display_buffer;
2139 tdm_nexell_display_destroy_buffer_list(tdm_nexell_display *display_data)
2141 tdm_nexell_display_buffer *b = NULL, *bb = NULL;
2143 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &display_data->buffer_list, link) {
2144 tbm_surface_internal_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, display_data);
2145 _tdm_nexell_display_cb_destroy_buffer(b->buffer, display_data);
2150 nexell_layer_set_buffer(tdm_nexell_layer *layer_data, tbm_surface_h buffer)
2152 tdm_nexell_display *display_data;
2153 tdm_nexell_display_buffer *display_buffer;
2154 hal_tdm_error err = HAL_TDM_ERROR_NONE;
2156 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2157 TDM_BACKEND_RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_INVALID_PARAMETER);
2159 display_data = layer_data->display_data;
2160 display_buffer = _tdm_nexell_display_find_buffer(display_data, buffer);
2161 if (!display_buffer) {
2162 display_buffer = _tdm_nexell_display_create_buffer(display_data, buffer, &err);
2163 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
2166 if (layer_data->display_buffer != display_buffer) {
2167 if (layer_data->display_buffer)
2168 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
2170 layer_data->display_buffer = display_buffer;
2171 tbm_surface_internal_ref(layer_data->display_buffer->buffer);
2172 layer_data->display_buffer_changed = 1;
2175 return HAL_TDM_ERROR_NONE;
2179 nexell_layer_unset_buffer(tdm_nexell_layer *layer_data)
2181 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2183 if (!(layer_data->capabilities & TDM_NEXELL_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) {
2184 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
2185 layer_data->display_buffer = NULL;
2188 layer_data->display_buffer_changed = 1;
2190 return HAL_TDM_ERROR_NONE;
2194 nexell_output_data_get_layer_data(tdm_nexell_output *output_data, int layer_zpos)
2196 tdm_nexell_layer *l = NULL;
2198 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, NULL);
2200 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
2201 if (l->zpos == layer_zpos)