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.");
1553 drmModeAtomicFree(request);
1554 return HAL_TDM_ERROR_OPERATION_FAILED;
1557 drmModeAtomicFree(request);
1559 return HAL_TDM_ERROR_NONE;
1562 static hal_tdm_error
1563 _nexell_output_layers_commit(hal_tdm_output *output, int sync, void *user_data)
1565 tdm_nexell_output *output_data = output;
1566 tdm_nexell_display *display_data;
1567 tdm_nexell_layer *layer_data = NULL;
1569 int do_waitvblank = 1;
1571 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1573 display_data = output_data->display_data;
1575 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1576 if (layer_data == output_data->primary_layer) {
1577 ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data,
1579 if (ret != HAL_TDM_ERROR_NONE)
1582 ret = _tdm_nexell_display_commit_layer(layer_data);
1583 if (ret != HAL_TDM_ERROR_NONE)
1588 if (do_waitvblank == 1) {
1589 tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
1593 TDM_BACKEND_ERR("alloc failed");
1594 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1597 ret = _tdm_nexell_display_get_cur_msc(display_data->drm_fd, output_data->pipe,
1599 if (ret != HAL_TDM_ERROR_NONE) {
1606 event_data->type = HAL_TDM_NEXELL_EVENT_TYPE_COMMIT;
1607 event_data->output_data = output_data;
1608 event_data->user_data = user_data;
1610 ret = _tdm_nexell_display_wait_vblank(display_data->drm_fd, output_data->pipe,
1611 &target_msc, event_data);
1612 if (ret != HAL_TDM_ERROR_NONE) {
1618 return HAL_TDM_ERROR_NONE;
1622 nexell_output_commit(hal_tdm_output *output, int sync, void *user_data)
1624 tdm_nexell_output *output_data = output;
1625 tdm_nexell_display *display_data;
1628 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1630 display_data = output_data->display_data;
1632 /* check the atomic pageflip */
1633 if (display_data->has_atomic) {
1634 ret = _nexell_output_atomic_commit(output, sync, user_data);
1635 if (ret != HAL_TDM_ERROR_NONE) {
1636 TDM_BACKEND_ERR("_nexell_output_atomic_commit failed.");
1640 ret = _nexell_output_layers_commit(output, sync, user_data);
1641 if (ret != HAL_TDM_ERROR_NONE) {
1642 TDM_BACKEND_ERR("_nexell_output_layers_commit failed.");
1647 return HAL_TDM_ERROR_NONE;
1651 nexell_output_set_commit_handler(hal_tdm_output *output,
1652 hal_tdm_output_commit_handler func)
1654 tdm_nexell_output *output_data = output;
1656 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1657 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1659 output_data->commit_func = func;
1661 return HAL_TDM_ERROR_NONE;
1665 nexell_output_set_dpms(hal_tdm_output *output, hal_tdm_output_dpms dpms_value)
1667 tdm_nexell_output *output_data = output;
1668 tdm_nexell_display *display_data;
1671 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1673 if (output_data->dpms_prop_id == 0) {
1674 TDM_BACKEND_WRN("not support DPMS");
1675 return HAL_TDM_ERROR_OPERATION_FAILED;
1678 display_data = output_data->display_data;
1679 ret = drmModeObjectSetProperty(display_data->drm_fd,
1680 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1681 output_data->dpms_prop_id, dpms_value);
1683 TDM_BACKEND_ERR("set dpms failed: %m");
1684 return HAL_TDM_ERROR_OPERATION_FAILED;
1687 return HAL_TDM_ERROR_NONE;
1691 nexell_output_get_dpms(hal_tdm_output *output, hal_tdm_output_dpms *dpms_value)
1693 tdm_nexell_output *output_data = output;
1694 tdm_nexell_display *display_data;
1695 drmModeObjectPropertiesPtr props;
1698 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1699 TDM_BACKEND_RETURN_VAL_IF_FAIL(dpms_value, HAL_TDM_ERROR_INVALID_PARAMETER);
1701 display_data = output_data->display_data;
1702 props = drmModeObjectGetProperties(display_data->drm_fd, output_data->connector_id,
1703 DRM_MODE_OBJECT_CONNECTOR);
1704 if (props == NULL) {
1705 TDM_BACKEND_ERR("get property failed: %m");
1706 return HAL_TDM_ERROR_OPERATION_FAILED;
1709 for (i = 0; i < props->count_props; i++)
1710 if (props->props[i] == output_data->dpms_prop_id) {
1711 *dpms_value = (uint)props->prop_values[i];
1715 drmModeFreeObjectProperties(props);
1717 return HAL_TDM_ERROR_NONE;
1721 nexell_output_set_mode(hal_tdm_output *output, const hal_tdm_output_mode *mode)
1723 tdm_nexell_output *output_data = output;
1724 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1726 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1727 TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER);
1729 /* create or replace the target_window when the output mode is set */
1730 ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
1731 if (ret != HAL_TDM_ERROR_NONE) {
1732 TDM_BACKEND_ERR("set info target hwc window failed (%d)", ret);
1736 output_data->current_mode = mode;
1737 output_data->mode_changed = 1;
1739 TDM_BACKEND_INFO("Set the output mode: %s, %d, %d, %d, %d, %d",
1740 mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
1742 return HAL_TDM_ERROR_NONE;
1746 nexell_output_get_mode(hal_tdm_output *output, const hal_tdm_output_mode **mode)
1748 tdm_nexell_output *output_data = output;
1750 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1751 TDM_BACKEND_RETURN_VAL_IF_FAIL(mode, HAL_TDM_ERROR_INVALID_PARAMETER);
1753 *mode = output_data->current_mode;
1755 return HAL_TDM_ERROR_NONE;
1759 nexell_output_get_hwc(hal_tdm_output *output, hal_tdm_error *error)
1761 tdm_nexell_hwc *hwc_data = NULL;
1762 tdm_nexell_output *output_data = output;
1763 hal_tdm_error ret = HAL_TDM_ERROR_NONE;
1767 TDM_BACKEND_ERR("invalid params");
1769 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
1773 if (output_data->hwc_data) {
1774 TDM_BACKEND_INFO("hwc_data already exists");
1776 *error = HAL_TDM_ERROR_NONE;
1777 return output_data->hwc_data;
1780 hwc_data = calloc(1, sizeof(tdm_nexell_hwc));
1782 TDM_BACKEND_ERR("alloc failed");
1784 *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
1788 for (i = 0; i < NUM_LAYERS; i++) {
1789 hwc_data->ui_buffer_queue[i].tqueue = NULL;
1790 hwc_data->ui_buffer_queue[i].ref_cnt = 0;
1793 hwc_data->output_data = output_data;
1795 LIST_INITHEAD(&hwc_data->hwc_window_list);
1797 output_data->hwc_data = hwc_data;
1799 ret = tdm_nexell_hwc_initailize_target_window(output_data->hwc_data);
1800 if (ret != HAL_TDM_ERROR_NONE) {
1801 TDM_BACKEND_ERR("create target hwc window failed (%d)", ret);
1809 *error = HAL_TDM_ERROR_NONE;
1815 nexell_output_set_status_handler(hal_tdm_output *output,
1816 hal_tdm_output_status_handler func,
1819 tdm_nexell_output *output_data = output;
1821 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1822 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1824 output_data->status_func = func;
1825 output_data->status_user_data = user_data;
1827 return HAL_TDM_ERROR_NONE;
1831 nexell_layer_get_capability(tdm_nexell_layer *layer_data, tdm_nexell_caps_layer *caps)
1833 tdm_nexell_display *display_data;
1834 drmModePlanePtr plane = NULL;
1835 drmModeObjectPropertiesPtr props = NULL;
1836 int i, format_count = 0;
1839 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1840 TDM_BACKEND_RETURN_VAL_IF_FAIL(caps, HAL_TDM_ERROR_INVALID_PARAMETER);
1842 memset(caps, 0, sizeof(tdm_nexell_caps_layer));
1844 display_data = layer_data->display_data;
1845 plane = drmModeGetPlane(display_data->drm_fd, layer_data->plane_id);
1847 TDM_BACKEND_ERR("get plane failed: %m");
1848 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1852 caps->capabilities = layer_data->capabilities;
1853 caps->zpos = layer_data->zpos; /* if VIDEO layer_data, zpos is -1 */
1855 caps->format_count = plane->count_formats;
1856 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1857 if (!caps->formats) {
1858 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1859 TDM_BACKEND_ERR("alloc failed\n");
1863 for (i = 0; i < caps->format_count; i++) {
1864 /* TODO: kernel reports wrong formats */
1865 if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
1866 plane->formats[i] != DRM_FORMAT_ARGB8888 &&
1867 plane->formats[i] != DRM_FORMAT_YUV420) {
1868 TDM_BACKEND_WRN("plane(%d) zpos(%d) %c%c%c%c skipped",
1869 layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i]));
1872 caps->formats[format_count] = tdm_nexell_format_to_tbm_format(plane->formats[i]);
1876 caps->format_count = format_count;
1878 props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id,
1879 DRM_MODE_OBJECT_PLANE);
1881 ret = HAL_TDM_ERROR_OPERATION_FAILED;
1882 TDM_BACKEND_ERR("get plane properties failed: %m\n");
1886 caps->props = calloc(1, sizeof(hal_tdm_prop) * props->count_props);
1888 ret = HAL_TDM_ERROR_OUT_OF_MEMORY;
1889 TDM_BACKEND_ERR("alloc failed\n");
1893 caps->prop_count = 0;
1894 for (i = 0; i < props->count_props; i++) {
1895 drmModePropertyPtr prop = drmModeGetProperty(display_data->drm_fd, props->props[i]);
1898 if (!strncmp(prop->name, "type", HAL_TDM_NAME_LEN)) {
1899 drmModeFreeProperty(prop);
1902 if (!strncmp(prop->name, "zpos", HAL_TDM_NAME_LEN)) {
1903 drmModeFreeProperty(prop);
1906 snprintf(caps->props[caps->prop_count].name, HAL_TDM_NAME_LEN, "%s", prop->name);
1907 caps->props[caps->prop_count].id = props->props[i];
1909 drmModeFreeProperty(prop);
1912 drmModeFreeObjectProperties(props);
1913 drmModeFreePlane(plane);
1915 return HAL_TDM_ERROR_NONE;
1917 drmModeFreeObjectProperties(props);
1918 drmModeFreePlane(plane);
1919 free(caps->formats);
1921 memset(caps, 0, sizeof(tdm_nexell_caps_layer));
1926 nexell_layer_set_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value value)
1928 tdm_nexell_display *display_data;
1931 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1932 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1934 display_data = layer_data->display_data;
1935 ret = drmModeObjectSetProperty(display_data->drm_fd,
1936 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
1939 TDM_BACKEND_ERR("set property failed: %m");
1940 return HAL_TDM_ERROR_OPERATION_FAILED;
1943 return HAL_TDM_ERROR_NONE;
1947 nexell_layer_get_property(tdm_nexell_layer *layer_data, unsigned int id, hal_tdm_value *value)
1949 tdm_nexell_display *display_data;
1950 drmModeObjectPropertiesPtr props;
1953 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1954 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, HAL_TDM_ERROR_INVALID_PARAMETER);
1955 TDM_BACKEND_RETURN_VAL_IF_FAIL(value, HAL_TDM_ERROR_INVALID_PARAMETER);
1957 display_data = layer_data->display_data;
1958 props = drmModeObjectGetProperties(display_data->drm_fd, layer_data->plane_id,
1959 DRM_MODE_OBJECT_PLANE);
1960 if (props == NULL) {
1961 TDM_BACKEND_ERR("get property failed: %m");
1962 return HAL_TDM_ERROR_OPERATION_FAILED;
1965 for (i = 0; i < props->count_props; i++)
1966 if (props->props[i] == id) {
1967 (*value).u32 = (uint)props->prop_values[i];
1971 drmModeFreeObjectProperties(props);
1973 return HAL_TDM_ERROR_NONE;
1977 nexell_layer_set_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info)
1979 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1980 TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
1982 layer_data->info = *info;
1983 layer_data->info_changed = 1;
1985 return HAL_TDM_ERROR_NONE;
1989 nexell_layer_get_info(tdm_nexell_layer *layer_data, tdm_nexell_layer_info *info)
1991 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
1992 TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
1994 *info = layer_data->info;
1996 return HAL_TDM_ERROR_NONE;
1999 static tdm_nexell_display_buffer *
2000 _tdm_nexell_display_find_buffer(tdm_nexell_display *display_data, tbm_surface_h buffer)
2002 tdm_nexell_display_buffer *display_buffer = NULL;
2004 LIST_FOR_EACH_ENTRY(display_buffer, &display_data->buffer_list, link) {
2005 if (display_buffer->buffer == buffer)
2006 return display_buffer;
2013 _tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
2015 tdm_nexell_display *display_data;
2016 tdm_nexell_display_buffer *display_buffer;
2017 tdm_nexell_layer *layer_data = NULL;
2018 tdm_nexell_output *output_data = NULL;
2019 char buf[256] = {0,};
2023 TDM_BACKEND_ERR("no user_data");
2027 TDM_BACKEND_ERR("no buffer");
2031 display_data = (tdm_nexell_display *) user_data;
2033 display_buffer = _tdm_nexell_display_find_buffer(display_data, buffer);
2034 if (!display_buffer) {
2035 TDM_BACKEND_ERR("no display_buffer");
2039 LIST_FOR_EACH_ENTRY(output_data, &display_data->output_list, link) {
2040 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
2041 if (display_buffer == layer_data->display_buffer)
2042 layer_data->display_buffer = NULL;
2046 if (display_buffer->fb_id > 0) {
2047 if (drmModeRmFB(display_data->drm_fd, display_buffer->fb_id) < 0) {
2048 ret_tmp = strerror_r(errno, buf, sizeof(buf));
2049 TDM_BACKEND_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
2053 TDM_BACKEND_DBG("destroy buffer:%p", display_buffer->buffer);
2055 LIST_DEL(&display_buffer->link);
2056 free(display_buffer);
2059 static tdm_nexell_display_buffer *
2060 _tdm_nexell_display_create_buffer(tdm_nexell_display *display_data, tbm_surface_h buffer, hal_tdm_error *err)
2062 tdm_nexell_display_buffer *display_buffer = NULL;
2065 display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer));
2066 if (!display_buffer) {
2067 TDM_BACKEND_ERR("alloc failed");
2069 *err = HAL_TDM_ERROR_OUT_OF_MEMORY;
2073 display_buffer->buffer = buffer;
2075 ret = tbm_surface_internal_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, display_data);
2077 TDM_BACKEND_ERR("add destroy handler fail");
2078 free(display_buffer);
2080 *err = HAL_TDM_ERROR_OPERATION_FAILED;
2084 display_buffer->width = tbm_surface_get_width(buffer);
2085 display_buffer->height = tbm_surface_get_height(buffer);
2086 display_buffer->format = tbm_surface_get_format(buffer);
2087 display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
2088 count = tbm_surface_internal_get_num_planes(display_buffer->format);
2089 TDM_BACKEND_DBG(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d",
2090 buffer, display_buffer->width, display_buffer->height,
2091 FOURCC_STR(display_buffer->format), display_buffer->count, count);
2093 for (i = 0; i < count; i++) {
2097 bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i);
2098 bo = tbm_surface_internal_get_bo(buffer, bo_idx);
2099 display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
2101 tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
2102 &display_buffer->offsets[i],
2103 &display_buffer->pitches[i]);
2104 TDM_BACKEND_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)",
2105 i, display_buffer->size, display_buffer->offsets[i],
2106 display_buffer->pitches[i], bo_idx, display_buffer->handles[i]);
2109 ret = drmModeAddFB2(display_data->drm_fd, display_buffer->width, display_buffer->height,
2110 display_buffer->format, display_buffer->handles, display_buffer->pitches,
2111 display_buffer->offsets, &display_buffer->fb_id, 0);
2113 TDM_BACKEND_ERR("add fb failed: %m");
2114 free(display_buffer);
2116 *err = HAL_TDM_ERROR_OPERATION_FAILED;
2117 tbm_surface_internal_remove_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, display_data);
2121 TDM_BACKEND_DBG("display_data->drm_fd : %d, display_buffer->fb_id:%u", display_data->drm_fd,
2122 display_buffer->fb_id);
2124 if (IS_RGB(display_buffer->format))
2125 display_buffer->width = display_buffer->pitches[0] >> 2;
2127 display_buffer->width = display_buffer->pitches[0];
2129 LIST_ADDTAIL(&display_buffer->link, &display_data->buffer_list);
2132 *err = HAL_TDM_ERROR_NONE;
2134 return display_buffer;
2138 tdm_nexell_display_destroy_buffer_list(tdm_nexell_display *display_data)
2140 tdm_nexell_display_buffer *b = NULL, *bb = NULL;
2142 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &display_data->buffer_list, link) {
2143 tbm_surface_internal_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, display_data);
2144 _tdm_nexell_display_cb_destroy_buffer(b->buffer, display_data);
2149 nexell_layer_set_buffer(tdm_nexell_layer *layer_data, tbm_surface_h buffer)
2151 tdm_nexell_display *display_data;
2152 tdm_nexell_display_buffer *display_buffer;
2153 hal_tdm_error err = HAL_TDM_ERROR_NONE;
2155 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2156 TDM_BACKEND_RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_INVALID_PARAMETER);
2158 display_data = layer_data->display_data;
2159 display_buffer = _tdm_nexell_display_find_buffer(display_data, buffer);
2160 if (!display_buffer) {
2161 display_buffer = _tdm_nexell_display_create_buffer(display_data, buffer, &err);
2162 TDM_BACKEND_RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
2165 if (layer_data->display_buffer != display_buffer) {
2166 if (layer_data->display_buffer)
2167 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
2169 layer_data->display_buffer = display_buffer;
2170 tbm_surface_internal_ref(layer_data->display_buffer->buffer);
2171 layer_data->display_buffer_changed = 1;
2174 return HAL_TDM_ERROR_NONE;
2178 nexell_layer_unset_buffer(tdm_nexell_layer *layer_data)
2180 TDM_BACKEND_RETURN_VAL_IF_FAIL(layer_data, HAL_TDM_ERROR_INVALID_PARAMETER);
2182 if (!(layer_data->capabilities & TDM_NEXELL_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) {
2183 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
2184 layer_data->display_buffer = NULL;
2187 layer_data->display_buffer_changed = 1;
2189 return HAL_TDM_ERROR_NONE;
2193 nexell_output_data_get_layer_data(tdm_nexell_output *output_data, int layer_zpos)
2195 tdm_nexell_layer *l = NULL;
2197 TDM_BACKEND_RETURN_VAL_IF_FAIL(output_data, NULL);
2199 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
2200 if (l->zpos == layer_zpos)