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 <drm_fourcc.h>
36 #include <tdm_helper.h>
38 #include "tdm_nexell.h"
39 #include "tdm_nexell_pp.h"
43 static drmModeModeInfoPtr
44 _tdm_nexell_display_get_mode(tdm_nexell_output_data *output_data)
48 if (!output_data->current_mode) {
49 TDM_ERR("no output_data->current_mode");
53 for (i = 0; i < output_data->count_modes; i++) {
54 drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i];
55 if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) &&
56 (drm_mode->vdisplay == output_data->current_mode->vdisplay) &&
57 (drm_mode->vrefresh == output_data->current_mode->vrefresh) &&
58 (drm_mode->flags == output_data->current_mode->flags) &&
59 (drm_mode->type == output_data->current_mode->type) &&
60 !(strncmp(drm_mode->name, output_data->current_mode->name, TDM_NAME_LEN)))
68 _tdm_nexell_display_to_tdm_mode(drmModeModeInfoPtr drm_mode,
69 tdm_output_mode *tdm_mode)
71 tdm_mode->clock = drm_mode->clock;
72 tdm_mode->hdisplay = drm_mode->hdisplay;
73 tdm_mode->hsync_start = drm_mode->hsync_start;
74 tdm_mode->hsync_end = drm_mode->hsync_end;
75 tdm_mode->htotal = drm_mode->htotal;
76 tdm_mode->hskew = drm_mode->hskew;
77 tdm_mode->vdisplay = drm_mode->vdisplay;
78 tdm_mode->vsync_start = drm_mode->vsync_start;
79 tdm_mode->vsync_end = drm_mode->vsync_end;
80 tdm_mode->vtotal = drm_mode->vtotal;
81 tdm_mode->vscan = drm_mode->vscan;
82 tdm_mode->vrefresh = drm_mode->vrefresh;
83 tdm_mode->flags = drm_mode->flags;
84 tdm_mode->type = drm_mode->type;
85 snprintf(tdm_mode->name, TDM_NAME_LEN, "%s", drm_mode->name);
89 _tdm_nexell_display_get_cur_msc (int fd, int pipe, uint *msc)
93 vbl.request.type = DRM_VBLANK_RELATIVE;
95 vbl.request.type |= DRM_VBLANK_SECONDARY;
97 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
99 vbl.request.sequence = 0;
100 if (drmWaitVBlank(fd, &vbl)) {
101 TDM_ERR("get vblank counter failed: %m");
103 return TDM_ERROR_OPERATION_FAILED;
106 *msc = vbl.reply.sequence;
108 return TDM_ERROR_NONE;
112 _tdm_nexell_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
116 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
118 vbl.request.type |= DRM_VBLANK_SECONDARY;
120 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
122 vbl.request.sequence = *target_msc;
123 vbl.request.signal = (unsigned long)(uintptr_t)data;
125 if (drmWaitVBlank(fd, &vbl)) {
126 TDM_ERR("wait vblank failed: %m");
128 return TDM_ERROR_OPERATION_FAILED;
131 *target_msc = vbl.reply.sequence;
133 return TDM_ERROR_NONE;
137 _tdm_nexell_output_update_status(tdm_nexell_output_data *output_data,
138 tdm_output_conn_status status)
140 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
142 if (output_data->status == status)
143 return TDM_ERROR_NONE;
145 output_data->status = status;
147 if (output_data->status_func)
148 output_data->status_func(output_data, status,
149 output_data->status_user_data);
151 return TDM_ERROR_NONE;
155 _tdm_nexell_display_commit_primary_layer(tdm_nexell_layer_data *layer_data,
156 void *user_data, int *do_waitvblank)
158 tdm_nexell_data *nexell_data = layer_data->nexell_data;
159 tdm_nexell_output_data *output_data = layer_data->output_data;
161 if (output_data->mode_changed && layer_data->display_buffer_changed) {
162 drmModeModeInfoPtr mode;
164 if (!layer_data->display_buffer) {
165 TDM_ERR("primary layer should have a buffer for modestting");
166 return TDM_ERROR_BAD_REQUEST;
169 output_data->mode_changed = 0;
170 layer_data->display_buffer_changed = 0;
171 layer_data->info_changed = 0;
173 mode = _tdm_nexell_display_get_mode(output_data);
175 TDM_ERR("couldn't find proper mode");
176 return TDM_ERROR_BAD_REQUEST;
179 if (drmModeSetCrtc(nexell_data->drm_fd, output_data->crtc_id,
180 layer_data->display_buffer->fb_id, 0, 0,
181 &output_data->connector_id, 1, mode)) {
182 TDM_ERR("set crtc failed: %m");
183 return TDM_ERROR_OPERATION_FAILED;
186 _tdm_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
189 return TDM_ERROR_NONE;
190 } else if (layer_data->display_buffer_changed) {
191 layer_data->display_buffer_changed = 0;
193 if (layer_data->display_buffer) {
194 tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
197 TDM_ERR("alloc failed");
198 return TDM_ERROR_OUT_OF_MEMORY;
201 event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
202 event_data->output_data = output_data;
203 event_data->user_data = user_data;
204 if (drmModePageFlip(nexell_data->drm_fd, output_data->crtc_id,
205 layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) {
206 TDM_ERR("pageflip failed: %m");
208 return TDM_ERROR_OPERATION_FAILED;
213 /* to call a user commit handler whenever committed */
217 return TDM_ERROR_NONE;
221 _tdm_nexell_display_commit_layer(tdm_nexell_layer_data *layer_data)
223 tdm_nexell_data *nexell_data = layer_data->nexell_data;
224 tdm_nexell_output_data *output_data = layer_data->output_data;
225 uint32_t fx, fy, fw, fh;
228 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
229 return TDM_ERROR_NONE;
231 if (output_data->current_mode)
232 crtc_w = output_data->current_mode->hdisplay;
234 drmModeCrtcPtr crtc = drmModeGetCrtc(nexell_data->drm_fd, output_data->crtc_id);
236 TDM_ERR("getting crtc failed");
237 return TDM_ERROR_OPERATION_FAILED;
239 crtc_w = crtc->width;
241 TDM_ERR("getting crtc width failed");
242 drmModeFreeCrtc(crtc);
243 return TDM_ERROR_OPERATION_FAILED;
245 drmModeFreeCrtc(crtc);
248 // reset the changed flags
249 layer_data->display_buffer_changed = 0;
250 layer_data->info_changed = 0;
252 if (layer_data->display_buffer) { // set plane
253 /* Source values are 16.16 fixed point */
254 fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
255 fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
256 fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
257 fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
259 TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
260 layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
261 layer_data->display_buffer->fb_id,
262 layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
263 layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
264 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
265 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
267 if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
268 output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
269 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
270 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
271 fx, fy, fw, fh) < 0) {
272 TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
273 return TDM_ERROR_OPERATION_FAILED;
275 } else { // unset plane
276 TDM_DBG("plane(%d) crtc(%d) pos(%d) : unset plane\n",
277 layer_data->plane_id, output_data->crtc_id, layer_data->zpos);
279 if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
280 output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
281 TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
284 return TDM_ERROR_NONE;
288 _tdm_nexell_display_cb_event(int fd, unsigned int sequence,
289 unsigned int tv_sec, unsigned int tv_usec,
292 tdm_nexell_event_data *event_data = user_data;
293 tdm_nexell_output_data *output_data;
294 tdm_nexell_hwc_data *hwc_data;
297 TDM_ERR("no event data");
301 output_data = event_data->output_data;
303 switch (event_data->type) {
304 case TDM_NEXELL_EVENT_TYPE_PAGEFLIP:
305 if (output_data->commit_func)
306 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
307 event_data->user_data);
309 case TDM_NEXELL_EVENT_TYPE_WAIT:
310 if (output_data->vblank_func)
311 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
312 event_data->user_data);
314 case TDM_NEXELL_EVENT_TYPE_COMMIT:
315 if (output_data->hwc_enable) {
316 hwc_data = output_data->hwc_data;
318 TDM_ERR("no hwc_data");
322 if (hwc_data->commit_func)
323 hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec,
324 event_data->user_data);
326 if (output_data->commit_func)
327 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
328 event_data->user_data);
339 _tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data)
341 tdm_nexell_output_data *output_data = NULL;
344 if (LIST_IS_EMPTY(&nexell_data->output_list)) {
345 TDM_ERR("no output");
346 return TDM_ERROR_OPERATION_FAILED;
349 /* The TDM drm backend only support one output. */
350 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
354 if (nexell_data->plane_res->count_planes == 0) {
355 TDM_ERR("no layer error");
356 return TDM_ERROR_OPERATION_FAILED;
359 for (i = 0; i < nexell_data->plane_res->count_planes; i++) {
360 tdm_nexell_layer_data *layer_data;
361 drmModePlanePtr plane;
363 plane = drmModeGetPlane(nexell_data->drm_fd, nexell_data->plane_res->planes[i]);
369 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
370 drmModeFreePlane(plane);
374 layer_data = calloc(1, sizeof(tdm_nexell_layer_data));
376 TDM_ERR("alloc failed");
377 drmModeFreePlane(plane);
381 layer_data->nexell_data = nexell_data;
382 layer_data->output_data = output_data;
383 layer_data->plane_id = nexell_data->plane_res->planes[i];
385 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
386 TDM_LAYER_CAPABILITY_GRAPHIC;
387 output_data->primary_layer = layer_data;
389 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
390 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
391 layer_data->capabilities);
393 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
395 drmModeFreePlane(plane);
397 /* can't take care of other planes for various hardware devices */
401 return TDM_ERROR_NONE;
404 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
407 _tdm_nexell_display_get_property(tdm_nexell_data *nexell_data,
408 unsigned int obj_id, unsigned int obj_type,
409 const char *name, unsigned int *value,
412 drmModeObjectPropertiesPtr props = NULL;
415 props = drmModeObjectGetProperties(nexell_data->drm_fd, obj_id, obj_type);
417 return TDM_ERROR_OPERATION_FAILED;
419 for (i = 0; i < props->count_props; i++) {
420 drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd,
426 if (!strcmp(prop->name, name)) {
428 *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
430 *value = (unsigned int)props->prop_values[i];
431 drmModeFreeProperty(prop);
432 drmModeFreeObjectProperties(props);
433 return TDM_ERROR_NONE;
436 drmModeFreeProperty(prop);
438 drmModeFreeObjectProperties(props);
439 TDM_DBG("coundn't find '%s' property", name);
440 return TDM_ERROR_OPERATION_FAILED;
444 _nexell_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id)
446 drmModeObjectPropertiesPtr properties = NULL;
447 drmModePropertyPtr property = NULL;
450 properties = drmModeObjectGetProperties(drm_fd, object_id, object_type);
451 if (properties == NULL) {
452 TDM_ERR("drmModeObjectGetProperties failed");
453 return TDM_ERROR_OPERATION_FAILED;
456 for (i = 0; i < properties->count_props; i++) {
457 property = drmModeGetProperty(drm_fd, properties->props[i]);
458 if (property == NULL) {
462 if (strcmp(property->name, name) == 0) {
463 *id = property->prop_id;
464 drmModeFreeProperty(property);
467 drmModeFreeProperty(property);
470 drmModeFreeObjectProperties(properties);
472 return TDM_ERROR_NONE;
476 _tdm_nexell_display_create_layer_list_type(tdm_nexell_data *nexell_data)
478 tdm_nexell_output_data *output_data = NULL;
479 drmModePlanePtr *planes = NULL;
480 unsigned int *types = NULL;
481 unsigned int type = 0;
482 int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt;
483 int opos_next, cpos_next;
487 if (LIST_IS_EMPTY(&nexell_data->output_list)) {
488 TDM_ERR("no output");
489 return TDM_ERROR_OPERATION_FAILED;
492 /* The TDM drm backend only support one output. */
493 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
497 ret = _tdm_nexell_display_get_property(nexell_data,
498 nexell_data->plane_res->planes[0],
499 DRM_MODE_OBJECT_PLANE, "type", &type,
501 if (ret != TDM_ERROR_NONE) {
502 TDM_ERR("plane doesn't have 'type' property. Call a fallback function");
504 /* if a plane doesn't have "type" property, we call a fallback function
507 return _tdm_nexell_display_create_layer_list(nexell_data);
510 planes = calloc(nexell_data->plane_res->count_planes, sizeof(drmModePlanePtr));
512 TDM_ERR("alloc failed");
516 types = calloc(nexell_data->plane_res->count_planes, sizeof(unsigned int));
518 TDM_ERR("alloc failed");
523 for (i = 0; i < nexell_data->plane_res->count_planes; i++) {
524 drmModePlanePtr plane;
526 plane = drmModeGetPlane(nexell_data->drm_fd, nexell_data->plane_res->planes[i]);
528 TDM_ERR("no plane(%d)", nexell_data->plane_res->planes[i]);
532 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
533 drmModeFreePlane(plane);
537 ret = _tdm_nexell_display_get_property(nexell_data,
538 nexell_data->plane_res->planes[i],
539 DRM_MODE_OBJECT_PLANE, "type", &type,
541 if (ret != TDM_ERROR_NONE) {
542 drmModeFreePlane(plane);
543 TDM_ERR("plane(%d) doesn't have 'type' info",
544 nexell_data->plane_res->planes[i]);
548 planes[plane_cnt] = plane;
549 types[plane_cnt] = type;
553 primary_cnt = ovl_cnt = cursor_cnt = 0;
554 for (i = 0; i < plane_cnt; i++) {
555 if (types[i] == DRM_PLANE_TYPE_CURSOR)
557 else if (types[i] == DRM_PLANE_TYPE_OVERLAY)
559 else if (types[i] == DRM_PLANE_TYPE_PRIMARY)
562 TDM_ERR("invalid type(%d)", types[i]);
565 if (primary_cnt != 1) {
566 TDM_ERR("primary layer count(%d) should be one", primary_cnt);
573 TDM_ERR("plane count(%d) should be over 1", plane_cnt);
577 for (i = plane_cnt - 1; i >= 0; i--) {
578 tdm_nexell_layer_data *layer_data;
580 layer_data = calloc(1, sizeof(tdm_nexell_layer_data));
582 TDM_ERR("alloc failed");
586 layer_data->nexell_data = nexell_data;
587 layer_data->output_data = output_data;
588 layer_data->plane_id = planes[i]->plane_id;
590 if (types[i] == DRM_PLANE_TYPE_CURSOR) {
591 layer_data->capabilities = TDM_LAYER_CAPABILITY_CURSOR |
592 TDM_LAYER_CAPABILITY_GRAPHIC |
593 TDM_LAYER_CAPABILITY_SCANOUT;
594 layer_data->zpos = cpos_next++;
595 TDM_INFO("layer_data(%p): cursor zpos(%d)", layer_data, layer_data->zpos);
596 } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
597 if (opos_next == 0) {
598 layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
599 TDM_LAYER_CAPABILITY_SCALE |
600 TDM_LAYER_CAPABILITY_SCANOUT;
602 layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
603 TDM_LAYER_CAPABILITY_GRAPHIC |
604 TDM_LAYER_CAPABILITY_RESEVED_MEMORY |
605 TDM_LAYER_CAPABILITY_SCANOUT;
607 if (opos_next == 1) {
608 layer_data->zpos = 2;
611 layer_data->zpos = opos_next++;
614 TDM_INFO("layer_data(%p): overlay zpos(%d)", layer_data, layer_data->zpos);
615 } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
616 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
617 TDM_LAYER_CAPABILITY_GRAPHIC |
618 TDM_LAYER_CAPABILITY_RESEVED_MEMORY |
619 TDM_LAYER_CAPABILITY_SCANOUT;
620 layer_data->zpos = 1;
621 output_data->primary_layer = layer_data;
623 TDM_INFO("layer_data(%p): primary zpos(%d)", layer_data, layer_data->zpos);
629 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
630 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
631 layer_data->zpos, layer_data->capabilities);
633 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
635 /* get the atomic prop ids*/
636 if (nexell_data->has_atomic) {
637 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
638 DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id);
639 if (ret != TDM_ERROR_NONE) {
644 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
645 DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id);
646 if (ret != TDM_ERROR_NONE) {
651 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
652 DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x);
653 if (ret != TDM_ERROR_NONE) {
658 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
659 DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y);
660 if (ret != TDM_ERROR_NONE) {
665 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
666 DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w);
667 if (ret != TDM_ERROR_NONE) {
672 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
673 DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h);
674 if (ret != TDM_ERROR_NONE) {
679 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
680 DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x);
681 if (ret != TDM_ERROR_NONE) {
686 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
687 DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y);
688 if (ret != TDM_ERROR_NONE) {
693 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
694 DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w);
695 if (ret != TDM_ERROR_NONE) {
700 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
701 DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h);
702 if (ret != TDM_ERROR_NONE) {
709 for (i = 0; i < plane_cnt; i++)
711 drmModeFreePlane(planes[i]);
716 return TDM_ERROR_NONE;
720 for (i = 0; i < nexell_data->plane_res->count_planes; i++)
722 drmModeFreePlane(planes[i]);
728 return TDM_ERROR_OPERATION_FAILED;
733 tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data)
735 tdm_nexell_output_data *output_data = NULL;
738 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
739 if (nexell_data->has_universal_plane)
740 ret = _tdm_nexell_display_create_layer_list_type(nexell_data);
743 ret = _tdm_nexell_display_create_layer_list(nexell_data);
745 if (ret != TDM_ERROR_NONE)
748 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
749 if (!output_data->primary_layer) {
750 TDM_ERR("output(%d) no primary layer", output_data->pipe);
751 return TDM_ERROR_OPERATION_FAILED;
755 return TDM_ERROR_NONE;
759 tdm_nexell_display_destroy_output_list(tdm_nexell_data *nexell_data)
761 tdm_nexell_output_data *o = NULL, *oo = NULL;
762 tdm_nexell_hwc_data *hwc_data = NULL;
764 if (LIST_IS_EMPTY(&nexell_data->output_list))
767 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &nexell_data->output_list, link) {
768 hwc_data = o->hwc_data;
769 if (hwc_data && hwc_data->target_hwc_window)
770 nexell_hwc_window_destroy(hwc_data->target_hwc_window);
773 if (!LIST_IS_EMPTY(&o->layer_list)) {
774 tdm_nexell_layer_data *l = NULL, *ll = NULL;
775 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
777 if (l->display_buffer)
778 tbm_surface_internal_unref(l->display_buffer->buffer);
783 free(o->output_modes);
789 tdm_nexell_display_update_output_status(tdm_nexell_data *nexell_data)
791 tdm_nexell_output_data *output_data = NULL;
793 if (LIST_IS_EMPTY(&nexell_data->output_list))
796 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
797 drmModeConnectorPtr connector;
798 tdm_output_conn_status new_status;
800 connector = drmModeGetConnector(nexell_data->drm_fd,
801 output_data->connector_id);
803 TDM_ERR("no connector: %d", output_data->connector_id);
807 if (connector->connection == DRM_MODE_CONNECTED)
808 new_status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
810 new_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
812 _tdm_nexell_output_update_status(output_data, new_status);
814 drmModeFreeConnector(connector);
819 tdm_nexell_display_create_output_list(tdm_nexell_data *nexell_data)
821 tdm_nexell_output_data *output_data;
825 drmModeConnectorPtr connector;
826 drmModeEncoderPtr encoder;
828 int hdmia_idx = -1, hdmib_idx = -1;
829 int crtc_id = 0, c, j;
831 RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&nexell_data->output_list),
832 TDM_ERROR_OPERATION_FAILED);
834 /* check if there is a connected output */
835 for (i = 0; i < nexell_data->mode_res->count_connectors; i++) {
836 connector = drmModeGetConnector(nexell_data->drm_fd,
837 nexell_data->mode_res->connectors[i]);
839 TDM_ERR("no connector");
840 return TDM_ERROR_OPERATION_FAILED;
843 /* The TDM drm backend considers only 1 connector because it is the TDM
844 * reference backend and can't take care of all hardware devices.
845 * To support various connectors, planes and crtcs, the new TDM backend
846 * should be implemented.
848 if (connector->connection == DRM_MODE_CONNECTED) {
850 drmModeFreeConnector(connector);
854 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
856 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
859 drmModeFreeConnector(connector);
862 /* use the hdmi connector if there is no connected connector. */
863 /* if there is no hdmi connector, use first connector. */
864 if (conn_idx == -1) {
866 conn_idx = hdmia_idx;
867 else if (hdmib_idx != -1)
868 conn_idx = hdmib_idx;
873 /* The TDM drm backend considers only 1 connector because it is the TDM
874 * reference backend and can't take care of all hardware devices.
875 * To support various connectors, planes and crtcs, the new TDM backend
876 * should be implemented.
878 connector = drmModeGetConnector(nexell_data->drm_fd,
879 nexell_data->mode_res->connectors[conn_idx]);
881 TDM_ERR("no connector");
882 ret = TDM_ERROR_OPERATION_FAILED;
886 if (connector->count_encoders != 1) {
887 TDM_ERR("too many encoders: %d", connector->count_encoders);
888 drmModeFreeConnector(connector);
889 ret = TDM_ERROR_OPERATION_FAILED;
893 encoder = drmModeGetEncoder(nexell_data->drm_fd, connector->encoders[0]);
895 TDM_ERR("no encoder");
896 drmModeFreeConnector(connector);
897 ret = TDM_ERROR_OPERATION_FAILED;
901 for (c = 0; c < nexell_data->mode_res->count_crtcs; c++) {
902 if ((encoder->possible_crtcs & (1 << c)) == 0)
905 crtc_id = nexell_data->mode_res->crtcs[c];
906 allocated |= (1 << c);
911 TDM_ERR("no possible crtc");
912 drmModeFreeConnector(connector);
913 drmModeFreeEncoder(encoder);
914 ret = TDM_ERROR_OPERATION_FAILED;
918 output_data = calloc(1, sizeof(tdm_nexell_output_data));
920 TDM_ERR("alloc failed");
921 drmModeFreeConnector(connector);
922 drmModeFreeEncoder(encoder);
923 ret = TDM_ERROR_OUT_OF_MEMORY;
927 LIST_INITHEAD(&output_data->layer_list);
929 output_data->nexell_data = nexell_data;
930 output_data->connector_id = nexell_data->mode_res->connectors[conn_idx];
931 output_data->encoder_id = encoder->encoder_id;
932 output_data->crtc_id = crtc_id;
933 output_data->pipe = c;
934 output_data->connector_type = connector->connector_type;
935 output_data->connector_type_id = connector->connector_type_id;
937 if (connector->connection == DRM_MODE_CONNECTED)
938 output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
940 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
942 for (j = 0; j < connector->count_props; j++) {
943 drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd,
944 connector->props[j]);
947 if (!strcmp(prop->name, "DPMS")) {
948 output_data->dpms_prop_id = connector->props[j];
949 drmModeFreeProperty(prop);
952 drmModeFreeProperty(prop);
955 if (output_data->dpms_prop_id == 0)
956 TDM_WRN("not support DPMS");
958 output_data->count_modes = connector->count_modes;
959 output_data->drm_modes = calloc(connector->count_modes,
960 sizeof(drmModeModeInfo));
961 if (!output_data->drm_modes) {
962 TDM_ERR("alloc failed");
964 drmModeFreeConnector(connector);
965 drmModeFreeEncoder(encoder);
966 ret = TDM_ERROR_OUT_OF_MEMORY;
969 output_data->output_modes = calloc(connector->count_modes,
970 sizeof(tdm_output_mode));
971 if (!output_data->output_modes) {
972 TDM_ERR("alloc failed");
973 free(output_data->drm_modes);
975 drmModeFreeConnector(connector);
976 drmModeFreeEncoder(encoder);
977 ret = TDM_ERROR_OUT_OF_MEMORY;
980 for (j = 0; j < connector->count_modes; j++) {
981 output_data->drm_modes[j] = connector->modes[j];
982 _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[j],
983 &output_data->output_modes[j]);
986 if (nexell_data->hwc_mode)
987 output_data->hwc_enable = 1;
989 LIST_ADDTAIL(&output_data->link, &nexell_data->output_list);
991 TDM_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
992 output_data, output_data->connector_id, output_data->status,
993 output_data->connector_type,
994 output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
995 output_data->pipe, output_data->dpms_prop_id);
997 drmModeFreeEncoder(encoder);
998 drmModeFreeConnector(connector);
1000 /* get the atomic prop ids*/
1001 if (nexell_data->has_atomic) {
1002 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->connector_id,
1003 DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id);
1004 if (ret != TDM_ERROR_NONE)
1007 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->crtc_id,
1008 DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id);
1009 if (ret != TDM_ERROR_NONE)
1012 ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->crtc_id,
1013 DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active);
1014 if (ret != TDM_ERROR_NONE)
1018 TDM_DBG("output count: %d", nexell_data->mode_res->count_connectors);
1020 return TDM_ERROR_NONE;
1022 tdm_nexell_display_destroy_output_list(nexell_data);
1027 nexell_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
1029 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1031 caps->max_layer_count = -1; /* not defined */
1033 return TDM_ERROR_NONE;
1037 nexell_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps)
1039 return tdm_nexell_pp_get_capability(bdata, caps);
1043 nexell_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
1045 tdm_nexell_data *nexell_data = bdata;
1046 tdm_nexell_output_data *output_data = NULL;
1047 tdm_output **outputs;
1051 RETURN_VAL_IF_FAIL(nexell_data, NULL);
1052 RETURN_VAL_IF_FAIL(count, NULL);
1055 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link)
1059 ret = TDM_ERROR_NONE;
1063 /* will be freed in frontend */
1064 outputs = calloc(*count, sizeof(tdm_nexell_output_data *));
1066 TDM_ERR("failed: alloc memory");
1068 ret = TDM_ERROR_OUT_OF_MEMORY;
1073 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link)
1074 outputs[i++] = output_data;
1077 *error = TDM_ERROR_NONE;
1087 nexell_display_get_fd(tdm_backend_data *bdata, int *fd)
1089 tdm_nexell_data *nexell_data = bdata;
1091 RETURN_VAL_IF_FAIL(nexell_data, TDM_ERROR_INVALID_PARAMETER);
1092 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
1094 *fd = nexell_data->drm_fd;
1096 return TDM_ERROR_NONE;
1100 nexell_display_handle_events(tdm_backend_data *bdata)
1102 tdm_nexell_data *nexell_data = bdata;
1103 drmEventContext ctx;
1105 RETURN_VAL_IF_FAIL(nexell_data, TDM_ERROR_INVALID_PARAMETER);
1107 memset(&ctx, 0, sizeof(drmEventContext));
1109 ctx.version = DRM_EVENT_CONTEXT_VERSION;
1110 ctx.page_flip_handler = _tdm_nexell_display_cb_event;
1111 ctx.vblank_handler = _tdm_nexell_display_cb_event;
1113 drmHandleEvent(nexell_data->drm_fd, &ctx);
1115 return TDM_ERROR_NONE;
1119 nexell_display_create_pp(tdm_backend_data *bdata, tdm_error *error)
1121 tdm_nexell_data *nexell_data = bdata;
1123 RETURN_VAL_IF_FAIL(nexell_data, NULL);
1125 return tdm_nexell_pp_create(nexell_data, error);
1129 nexell_output_get_capability(tdm_output *output, tdm_caps_output *caps)
1131 tdm_nexell_output_data *output_data = output;
1132 tdm_nexell_data *nexell_data;
1133 drmModeConnectorPtr connector = NULL;
1134 drmModeCrtcPtr crtc = NULL;
1135 drmModeObjectPropertiesPtr props = NULL;
1139 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1140 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1142 memset(caps, 0, sizeof(tdm_caps_output));
1144 nexell_data = output_data->nexell_data;
1146 snprintf(caps->maker, TDM_NAME_LEN, "unknown");
1147 snprintf(caps->model, TDM_NAME_LEN, "unknown");
1148 snprintf(caps->name, TDM_NAME_LEN, "unknown");
1150 caps->status = output_data->status;
1151 caps->type = output_data->connector_type;
1152 caps->type_id = output_data->connector_type_id;
1154 connector = drmModeGetConnector(nexell_data->drm_fd, output_data->connector_id);
1155 RETURN_VAL_IF_FAIL(connector, TDM_ERROR_OPERATION_FAILED);
1157 caps->mode_count = connector->count_modes;
1158 caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count);
1160 ret = TDM_ERROR_OUT_OF_MEMORY;
1161 TDM_ERR("alloc failed\n");
1165 if (caps->mode_count != output_data->count_modes) {
1166 drmModeModeInfoPtr new_drm_modes;
1167 tdm_output_mode *new_output_modes;
1169 new_drm_modes = calloc(connector->count_modes,
1170 sizeof(drmModeModeInfo));
1171 if (!new_drm_modes) {
1172 ret = TDM_ERROR_OUT_OF_MEMORY;
1173 TDM_ERR("alloc failed drm_modes\n");
1176 new_output_modes = calloc(connector->count_modes,
1177 sizeof(tdm_output_mode));
1178 if (!new_output_modes) {
1179 ret = TDM_ERROR_OUT_OF_MEMORY;
1180 TDM_ERR("alloc failed output_modes\n");
1181 free(new_drm_modes);
1184 free(output_data->drm_modes);
1185 free(output_data->output_modes);
1187 output_data->drm_modes = new_drm_modes;
1188 output_data->output_modes = new_output_modes;
1189 output_data->count_modes = caps->mode_count;
1192 for (i = 0; i < caps->mode_count; i++) {
1193 output_data->drm_modes[i] = connector->modes[i];
1194 _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[i],
1195 &output_data->output_modes[i]);
1196 caps->modes[i] = output_data->output_modes[i];
1199 caps->mmWidth = connector->mmWidth;
1200 caps->mmHeight = connector->mmHeight;
1201 caps->subpixel = connector->subpixel;
1203 caps->min_w = nexell_data->mode_res->min_width;
1204 caps->min_h = nexell_data->mode_res->min_height;
1205 caps->max_w = nexell_data->mode_res->max_width;
1206 caps->max_h = nexell_data->mode_res->max_height;
1207 caps->preferred_align = -1;
1209 crtc = drmModeGetCrtc(nexell_data->drm_fd, output_data->crtc_id);
1211 ret = TDM_ERROR_OPERATION_FAILED;
1212 TDM_ERR("get crtc failed: %m\n");
1216 props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->crtc_id,
1217 DRM_MODE_OBJECT_CRTC);
1219 ret = TDM_ERROR_OPERATION_FAILED;
1220 TDM_ERR("get crtc properties failed: %m\n");
1224 caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
1226 ret = TDM_ERROR_OUT_OF_MEMORY;
1227 TDM_ERR("alloc failed\n");
1231 caps->prop_count = 0;
1232 for (i = 0; i < props->count_props; i++) {
1233 drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, props->props[i]);
1236 snprintf(caps->props[caps->prop_count].name, TDM_NAME_LEN, "%s", prop->name);
1237 caps->props[caps->prop_count].id = props->props[i];
1239 drmModeFreeProperty(prop);
1242 if (output_data->hwc_enable) {
1243 caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
1246 drmModeFreeObjectProperties(props);
1247 drmModeFreeCrtc(crtc);
1248 drmModeFreeConnector(connector);
1250 return TDM_ERROR_NONE;
1252 drmModeFreeCrtc(crtc);
1253 drmModeFreeObjectProperties(props);
1254 drmModeFreeConnector(connector);
1257 memset(caps, 0, sizeof(tdm_caps_output));
1262 nexell_output_get_layers(tdm_output *output, int *count, tdm_error *error)
1264 tdm_nexell_output_data *output_data = output;
1265 tdm_nexell_layer_data *layer_data = NULL;
1270 RETURN_VAL_IF_FAIL(output_data, NULL);
1271 RETURN_VAL_IF_FAIL(count, NULL);
1274 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1277 if (output_data->hwc_enable) {
1279 ret = TDM_ERROR_NONE;
1284 ret = TDM_ERROR_NONE;
1288 /* will be freed in frontend */
1289 layers = calloc(*count, sizeof(tdm_nexell_layer_data *));
1291 TDM_ERR("failed: alloc memory");
1293 ret = TDM_ERROR_OUT_OF_MEMORY;
1298 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1299 layers[i++] = layer_data;
1302 *error = TDM_ERROR_NONE;
1312 nexell_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
1314 tdm_nexell_output_data *output_data = output;
1315 tdm_nexell_data *nexell_data;
1318 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1319 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1321 nexell_data = output_data->nexell_data;
1322 ret = drmModeObjectSetProperty(nexell_data->drm_fd,
1323 output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
1326 TDM_ERR("set property failed: %m");
1327 return TDM_ERROR_OPERATION_FAILED;
1330 return TDM_ERROR_NONE;
1334 nexell_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
1336 tdm_nexell_output_data *output_data = output;
1337 tdm_nexell_data *nexell_data;
1338 drmModeObjectPropertiesPtr props;
1341 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1342 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1343 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1345 nexell_data = output_data->nexell_data;
1346 props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->crtc_id,
1347 DRM_MODE_OBJECT_CRTC);
1348 if (props == NULL) {
1349 TDM_ERR("get property failed: %m");
1350 return TDM_ERROR_OPERATION_FAILED;
1353 for (i = 0; i < props->count_props; i++)
1354 if (props->props[i] == id) {
1355 (*value).u32 = (uint)props->prop_values[i];
1359 drmModeFreeObjectProperties(props);
1361 return TDM_ERROR_NONE;
1365 nexell_output_wait_vblank(tdm_output *output, int interval, int sync,
1368 tdm_nexell_output_data *output_data = output;
1369 tdm_nexell_data *nexell_data;
1370 tdm_nexell_event_data *event_data;
1374 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1376 event_data = calloc(1, sizeof(tdm_nexell_event_data));
1378 TDM_ERR("alloc failed");
1379 return TDM_ERROR_OUT_OF_MEMORY;
1382 nexell_data = output_data->nexell_data;
1384 ret = _tdm_nexell_display_get_cur_msc(nexell_data->drm_fd, output_data->pipe,
1386 if (ret != TDM_ERROR_NONE)
1389 target_msc += interval;
1391 event_data->type = TDM_NEXELL_EVENT_TYPE_WAIT;
1392 event_data->output_data = output_data;
1393 event_data->user_data = user_data;
1395 ret = _tdm_nexell_display_wait_vblank(nexell_data->drm_fd, output_data->pipe,
1396 &target_msc, event_data);
1397 if (ret != TDM_ERROR_NONE)
1400 return TDM_ERROR_NONE;
1407 nexell_output_set_vblank_handler(tdm_output *output,
1408 tdm_output_vblank_handler func)
1410 tdm_nexell_output_data *output_data = output;
1412 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1413 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1415 output_data->vblank_func = func;
1417 return TDM_ERROR_NONE;
1421 _nexell_layer_add_atomic_properties(tdm_nexell_layer_data *layer_data, drmModeAtomicReqPtr request,
1422 uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
1423 uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h)
1425 tdm_error ret = TDM_ERROR_NONE;
1427 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id);
1429 TDM_ERR("fail to add the atomic prop. fb_id(%u)", fb_id);
1430 return TDM_ERROR_OPERATION_FAILED;
1433 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id);
1435 TDM_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id);
1436 return TDM_ERROR_OPERATION_FAILED;
1439 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x);
1441 TDM_ERR("fail to add the atomic prop. src_x(%u)", src_x);
1442 return TDM_ERROR_OPERATION_FAILED;
1445 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y);
1447 TDM_ERR("fail to add the atomic prop. src_y(%u)", src_y);
1448 return TDM_ERROR_OPERATION_FAILED;
1451 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w);
1453 TDM_ERR("fail to add the atomic prop. src_w(%u)", src_w);
1454 return TDM_ERROR_OPERATION_FAILED;
1457 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h);
1459 TDM_ERR("fail to add the atomic prop. src_h(%u)", src_h);
1460 return TDM_ERROR_OPERATION_FAILED;
1463 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x);
1465 TDM_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x);
1466 return TDM_ERROR_OPERATION_FAILED;
1469 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y);
1471 TDM_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y);
1472 return TDM_ERROR_OPERATION_FAILED;
1475 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w);
1477 TDM_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w);
1478 return TDM_ERROR_OPERATION_FAILED;
1481 ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h);
1483 TDM_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h);
1484 return TDM_ERROR_OPERATION_FAILED;
1487 return TDM_ERROR_NONE;
1491 _nexell_layer_make_atomic_request(tdm_nexell_layer_data *layer_data, drmModeAtomicReqPtr request)
1493 tdm_nexell_data *nexell_data = layer_data->nexell_data;
1494 tdm_nexell_output_data *output_data = layer_data->output_data;
1495 uint32_t fx, fy, fw, fh;
1496 tdm_info_layer layer_info = layer_data->info;
1497 tdm_error ret = TDM_ERROR_NONE;
1499 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
1500 return TDM_ERROR_NONE;
1502 layer_data->display_buffer_changed = 0;
1503 layer_data->info_changed = 0;
1505 if (!layer_data->display_buffer) {
1506 TDM_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off",
1507 nexell_data->drm_fd, layer_data->plane_id, output_data->crtc_id);
1509 ret = _nexell_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1510 if (ret != TDM_ERROR_NONE) {
1511 TDM_ERR("_nexell_layer_add_atomic_properties failed.");
1515 return TDM_ERROR_NONE;
1518 /* Source values are 16.16 fixed point */
1519 fx = ((unsigned int)layer_info.src_config.pos.x) << 16;
1520 fy = ((unsigned int)layer_info.src_config.pos.y) << 16;
1521 fw = ((unsigned int)layer_info.src_config.pos.w) << 16;
1522 fh = ((unsigned int)layer_info.src_config.pos.h) << 16;
1524 TDM_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)",
1525 nexell_data->drm_fd, layer_data->plane_id, layer_data->zpos,
1526 output_data->crtc_id, layer_data->display_buffer->fb_id,
1527 layer_info.src_config.pos.x, layer_info.src_config.pos.y,
1528 layer_info.src_config.pos.w, layer_info.src_config.pos.h,
1529 layer_info.dst_pos.x, layer_info.dst_pos.y,
1530 layer_info.dst_pos.w, layer_info.dst_pos.h);
1532 ret = _nexell_layer_add_atomic_properties(layer_data, request,
1533 layer_data->display_buffer->fb_id, output_data->crtc_id,
1535 layer_info.dst_pos.x, layer_info.dst_pos.y,
1536 layer_info.dst_pos.w, layer_info.dst_pos.h);
1537 if (ret != TDM_ERROR_NONE) {
1538 TDM_ERR("MakeAtomicRequest failed");
1542 return TDM_ERROR_NONE;
1546 _nexell_output_atomic_commit(tdm_output *output, int sync, void *user_data)
1548 tdm_nexell_output_data *output_data = output;
1549 tdm_nexell_layer_data *layer_data = NULL;
1550 tdm_nexell_event_data *event_data;
1551 drmModeAtomicReqPtr request;
1555 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1557 if (!output_data->crtc_enabled || output_data->mode_changed) {
1558 drmModeModeInfoPtr mode;
1560 layer_data = output_data->primary_layer;
1561 if (!layer_data->display_buffer) {
1562 TDM_ERR("primary layer should have a buffer for modestting");
1563 return TDM_ERROR_BAD_REQUEST;
1566 mode = _tdm_nexell_display_get_mode(output_data);
1568 TDM_ERR("couldn't find proper mode");
1569 return TDM_ERROR_BAD_REQUEST;
1572 if (drmModeSetCrtc(output_data->nexell_data->drm_fd, output_data->crtc_id,
1573 layer_data->display_buffer->fb_id, 0, 0,
1574 &output_data->connector_id, 1, mode)) {
1575 TDM_ERR("set crtc failed: %m");
1576 return TDM_ERROR_OPERATION_FAILED;
1579 _tdm_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
1581 output_data->crtc_enabled = 1;
1582 output_data->mode_changed = 0;
1585 request = drmModeAtomicAlloc();
1587 TDM_ERR("drmModeAtomicAlloc failed.");
1588 return TDM_ERROR_OUT_OF_MEMORY;
1591 flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
1593 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1594 ret = _nexell_layer_make_atomic_request(layer_data, request);
1595 if (ret != TDM_ERROR_NONE) {
1596 TDM_ERR("_nexell_layer_make_atomic_request failed.");
1597 drmModeAtomicFree(request);
1602 event_data = calloc(1, sizeof(tdm_nexell_event_data));
1604 TDM_ERR("fail to alloc event_data.");
1605 drmModeAtomicFree(request);
1606 return TDM_ERROR_OUT_OF_MEMORY;
1609 event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
1610 event_data->output_data = output_data;
1611 event_data->user_data = user_data;
1613 TDM_DBG("==== Atomic Commit pipe, %u, crtc_id, %u connector_id, %u",
1614 output_data->pipe, output_data->crtc_id, output_data->connector_id);
1616 if (drmModeAtomicCommit(output_data->nexell_data->drm_fd, request, flags, event_data) < 0) {
1617 TDM_ERR("drmModeAtomicCommit failed.");
1619 drmModeAtomicFree(request);
1620 return TDM_ERROR_OPERATION_FAILED;
1623 drmModeAtomicFree(request);
1625 return TDM_ERROR_NONE;
1629 _nexell_output_layers_commit(tdm_output *output, int sync, void *user_data)
1631 tdm_nexell_output_data *output_data = output;
1632 tdm_nexell_data *nexell_data;
1633 tdm_nexell_layer_data *layer_data = NULL;
1635 int do_waitvblank = 1;
1637 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1639 nexell_data = output_data->nexell_data;
1641 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1642 if (layer_data == output_data->primary_layer) {
1643 ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data,
1645 if (ret != TDM_ERROR_NONE)
1648 ret = _tdm_nexell_display_commit_layer(layer_data);
1649 if (ret != TDM_ERROR_NONE)
1654 if (do_waitvblank == 1) {
1655 tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
1659 TDM_ERR("alloc failed");
1660 return TDM_ERROR_OUT_OF_MEMORY;
1663 ret = _tdm_nexell_display_get_cur_msc(nexell_data->drm_fd, output_data->pipe,
1665 if (ret != TDM_ERROR_NONE) {
1672 event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
1673 event_data->output_data = output_data;
1674 event_data->user_data = user_data;
1676 ret = _tdm_nexell_display_wait_vblank(nexell_data->drm_fd, output_data->pipe,
1677 &target_msc, event_data);
1678 if (ret != TDM_ERROR_NONE) {
1684 return TDM_ERROR_NONE;
1688 nexell_output_commit(tdm_output *output, int sync, void *user_data)
1690 tdm_nexell_output_data *output_data = output;
1691 tdm_nexell_data *nexell_data;
1694 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1696 nexell_data = output_data->nexell_data;
1698 /* check the atomic pageflip */
1699 if (nexell_data->has_atomic) {
1700 ret = _nexell_output_atomic_commit(output, sync, user_data);
1701 if (ret != TDM_ERROR_NONE) {
1702 TDM_ERR("_nexell_output_atomic_commit failed.");
1706 ret = _nexell_output_layers_commit(output, sync, user_data);
1707 if (ret != TDM_ERROR_NONE) {
1708 TDM_ERR("_nexell_output_layers_commit failed.");
1713 return TDM_ERROR_NONE;
1717 nexell_output_set_commit_handler(tdm_output *output,
1718 tdm_output_commit_handler func)
1720 tdm_nexell_output_data *output_data = output;
1722 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1723 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1725 output_data->commit_func = func;
1727 return TDM_ERROR_NONE;
1731 nexell_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1733 tdm_nexell_output_data *output_data = output;
1734 tdm_nexell_data *nexell_data;
1737 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1739 if (output_data->dpms_prop_id == 0) {
1740 TDM_WRN("not support DPMS");
1741 return TDM_ERROR_OPERATION_FAILED;
1744 nexell_data = output_data->nexell_data;
1745 ret = drmModeObjectSetProperty(nexell_data->drm_fd,
1746 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1747 output_data->dpms_prop_id, dpms_value);
1749 TDM_ERR("set dpms failed: %m");
1750 return TDM_ERROR_OPERATION_FAILED;
1753 return TDM_ERROR_NONE;
1757 nexell_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1759 tdm_nexell_output_data *output_data = output;
1760 tdm_nexell_data *nexell_data;
1761 drmModeObjectPropertiesPtr props;
1764 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1765 RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
1767 nexell_data = output_data->nexell_data;
1768 props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->connector_id,
1769 DRM_MODE_OBJECT_CONNECTOR);
1770 if (props == NULL) {
1771 TDM_ERR("get property failed: %m");
1772 return TDM_ERROR_OPERATION_FAILED;
1775 for (i = 0; i < props->count_props; i++)
1776 if (props->props[i] == output_data->dpms_prop_id) {
1777 *dpms_value = (uint)props->prop_values[i];
1781 drmModeFreeObjectProperties(props);
1783 return TDM_ERROR_NONE;
1787 nexell_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1789 tdm_nexell_output_data *output_data = output;
1790 tdm_error ret = TDM_ERROR_NONE;
1792 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1793 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1795 /* create or replace the target_window when the output mode is set */
1796 if (output_data->hwc_enable) {
1797 ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
1798 if (ret != TDM_ERROR_NONE) {
1799 TDM_ERR("set info target hwc window failed (%d)", ret);
1804 output_data->current_mode = mode;
1805 output_data->mode_changed = 1;
1807 TDM_INFO("Set the output mode: %s, %d, %d, %d, %d, %d",
1808 mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
1810 return TDM_ERROR_NONE;
1814 nexell_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1816 tdm_nexell_output_data *output_data = output;
1818 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1819 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1821 *mode = output_data->current_mode;
1823 return TDM_ERROR_NONE;
1827 nexell_output_get_hwc(tdm_output *output, tdm_error *error)
1829 tdm_nexell_hwc_data *hwc_data = NULL;
1830 tdm_nexell_output_data *output_data = output;
1831 tdm_error ret = TDM_ERROR_NONE;
1835 TDM_ERR("invalid params");
1837 *error = TDM_ERROR_INVALID_PARAMETER;
1841 if (output_data->hwc_data) {
1842 TDM_INFO("hwc_data already exists");
1844 *error = TDM_ERROR_NONE;
1845 return output_data->hwc_data;
1848 hwc_data = calloc(1, sizeof(tdm_nexell_hwc_data));
1850 TDM_ERR("alloc failed");
1852 *error = TDM_ERROR_OUT_OF_MEMORY;
1856 for (i = 0; i < NUM_LAYERS; i++) {
1857 hwc_data->ui_buffer_queue[i].tqueue = NULL;
1858 hwc_data->ui_buffer_queue[i].ref_cnt = 0;
1861 hwc_data->output_data = output_data;
1863 LIST_INITHEAD(&hwc_data->hwc_window_list);
1865 output_data->hwc_data = hwc_data;
1867 ret = nexell_hwc_initailize_target_window(output_data->hwc_data);
1868 if (ret != TDM_ERROR_NONE) {
1869 TDM_ERR("create target hwc window failed (%d)", ret);
1877 *error = TDM_ERROR_NONE;
1883 nexell_output_set_status_handler(tdm_output *output,
1884 tdm_output_status_handler func,
1887 tdm_nexell_output_data *output_data = output;
1889 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1890 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1892 output_data->status_func = func;
1893 output_data->status_user_data = user_data;
1895 return TDM_ERROR_NONE;
1899 nexell_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
1901 tdm_nexell_layer_data *layer_data = layer;
1902 tdm_nexell_data *nexell_data;
1903 drmModePlanePtr plane = NULL;
1904 drmModeObjectPropertiesPtr props = NULL;
1905 int i, format_count = 0;
1908 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1909 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1911 memset(caps, 0, sizeof(tdm_caps_layer));
1913 nexell_data = layer_data->nexell_data;
1914 plane = drmModeGetPlane(nexell_data->drm_fd, layer_data->plane_id);
1916 TDM_ERR("get plane failed: %m");
1917 ret = TDM_ERROR_OPERATION_FAILED;
1921 caps->capabilities = layer_data->capabilities;
1922 caps->zpos = layer_data->zpos; /* if VIDEO layer, zpos is -1 */
1924 caps->format_count = plane->count_formats;
1925 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1926 if (!caps->formats) {
1927 ret = TDM_ERROR_OUT_OF_MEMORY;
1928 TDM_ERR("alloc failed\n");
1932 for (i = 0; i < caps->format_count; i++) {
1933 /* TODO: kernel reports wrong formats */
1934 if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
1935 plane->formats[i] != DRM_FORMAT_ARGB8888 &&
1936 plane->formats[i] != DRM_FORMAT_YUV420) {
1937 TDM_WRN("plane(%d) zpos(%d) %c%c%c%c skipped",
1938 layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i]));
1941 caps->formats[format_count] = tdm_nexell_format_to_tbm_format(plane->formats[i]);
1945 caps->format_count = format_count;
1947 props = drmModeObjectGetProperties(nexell_data->drm_fd, layer_data->plane_id,
1948 DRM_MODE_OBJECT_PLANE);
1950 ret = TDM_ERROR_OPERATION_FAILED;
1951 TDM_ERR("get plane properties failed: %m\n");
1955 caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
1957 ret = TDM_ERROR_OUT_OF_MEMORY;
1958 TDM_ERR("alloc failed\n");
1962 caps->prop_count = 0;
1963 for (i = 0; i < props->count_props; i++) {
1964 drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, props->props[i]);
1967 if (!strncmp(prop->name, "type", TDM_NAME_LEN)) {
1968 drmModeFreeProperty(prop);
1971 if (!strncmp(prop->name, "zpos", TDM_NAME_LEN)) {
1972 drmModeFreeProperty(prop);
1975 snprintf(caps->props[caps->prop_count].name, TDM_NAME_LEN, "%s", prop->name);
1976 caps->props[caps->prop_count].id = props->props[i];
1978 drmModeFreeProperty(prop);
1981 drmModeFreeObjectProperties(props);
1982 drmModeFreePlane(plane);
1984 return TDM_ERROR_NONE;
1986 drmModeFreeObjectProperties(props);
1987 drmModeFreePlane(plane);
1988 free(caps->formats);
1990 memset(caps, 0, sizeof(tdm_caps_layer));
1995 nexell_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1997 tdm_nexell_layer_data *layer_data = layer;
1998 tdm_nexell_data *nexell_data;
2001 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
2002 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
2004 nexell_data = layer_data->nexell_data;
2005 ret = drmModeObjectSetProperty(nexell_data->drm_fd,
2006 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
2009 TDM_ERR("set property failed: %m");
2010 return TDM_ERROR_OPERATION_FAILED;
2013 return TDM_ERROR_NONE;
2017 nexell_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
2019 tdm_nexell_layer_data *layer_data = layer;
2020 tdm_nexell_data *nexell_data;
2021 drmModeObjectPropertiesPtr props;
2024 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
2025 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
2026 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
2028 nexell_data = layer_data->nexell_data;
2029 props = drmModeObjectGetProperties(nexell_data->drm_fd, layer_data->plane_id,
2030 DRM_MODE_OBJECT_PLANE);
2031 if (props == NULL) {
2032 TDM_ERR("get property failed: %m");
2033 return TDM_ERROR_OPERATION_FAILED;
2036 for (i = 0; i < props->count_props; i++)
2037 if (props->props[i] == id) {
2038 (*value).u32 = (uint)props->prop_values[i];
2042 drmModeFreeObjectProperties(props);
2044 return TDM_ERROR_NONE;
2048 nexell_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
2050 tdm_nexell_layer_data *layer_data = layer;
2052 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
2053 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
2055 layer_data->info = *info;
2056 layer_data->info_changed = 1;
2058 return TDM_ERROR_NONE;
2062 nexell_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
2064 tdm_nexell_layer_data *layer_data = layer;
2066 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
2067 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
2069 *info = layer_data->info;
2071 return TDM_ERROR_NONE;
2074 static tdm_nexell_display_buffer *
2075 _tdm_nexell_display_find_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer)
2077 tdm_nexell_display_buffer *display_buffer = NULL;
2079 LIST_FOR_EACH_ENTRY(display_buffer, &nexell_data->buffer_list, link) {
2080 if (display_buffer->buffer == buffer)
2081 return display_buffer;
2088 _tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
2090 tdm_nexell_data *nexell_data;
2091 tdm_nexell_display_buffer *display_buffer;
2092 tdm_nexell_layer_data *layer_data = NULL;
2093 tdm_nexell_output_data *output_data = NULL;
2094 char buf[256] = {0,};
2098 TDM_ERR("no user_data");
2102 TDM_ERR("no buffer");
2106 nexell_data = (tdm_nexell_data *) user_data;
2108 display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer);
2109 if (!display_buffer) {
2110 TDM_ERR("no display_buffer");
2114 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
2115 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
2116 if (display_buffer == layer_data->display_buffer)
2117 layer_data->display_buffer = NULL;
2121 if (display_buffer->fb_id > 0) {
2122 if (drmModeRmFB(nexell_data->drm_fd, display_buffer->fb_id) < 0) {
2123 ret_tmp = strerror_r(errno, buf, sizeof(buf));
2124 TDM_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
2128 TDM_DBG("destroy buffer:%p", display_buffer->buffer);
2130 LIST_DEL(&display_buffer->link);
2131 free(display_buffer);
2134 static tdm_nexell_display_buffer *
2135 _tdm_nexell_display_create_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer, tdm_error *err)
2137 tdm_nexell_display_buffer *display_buffer = NULL;
2138 tdm_error res = TDM_ERROR_NONE;
2141 display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer));
2142 if (!display_buffer) {
2143 TDM_ERR("alloc failed");
2145 *err = TDM_ERROR_OUT_OF_MEMORY;
2149 display_buffer->buffer = buffer;
2151 res = tdm_buffer_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data);
2152 if (res != TDM_ERROR_NONE) {
2153 TDM_ERR("add destroy handler fail");
2154 free(display_buffer);
2160 display_buffer->width = tbm_surface_get_width(buffer);
2161 display_buffer->height = tbm_surface_get_height(buffer);
2162 display_buffer->format = tbm_surface_get_format(buffer);
2163 display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
2164 count = tbm_surface_internal_get_num_planes(display_buffer->format);
2165 TDM_DBG(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d",
2166 buffer, display_buffer->width, display_buffer->height,
2167 FOURCC_STR(display_buffer->format), display_buffer->count, count);
2169 for (i = 0; i < count; i++) {
2173 bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i);
2174 bo = tbm_surface_internal_get_bo(buffer, bo_idx);
2175 display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
2177 tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
2178 &display_buffer->offsets[i],
2179 &display_buffer->pitches[i]);
2180 TDM_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)",
2181 i, display_buffer->size, display_buffer->offsets[i],
2182 display_buffer->pitches[i], bo_idx, display_buffer->handles[i]);
2185 ret = drmModeAddFB2(nexell_data->drm_fd, display_buffer->width, display_buffer->height,
2186 display_buffer->format, display_buffer->handles, display_buffer->pitches,
2187 display_buffer->offsets, &display_buffer->fb_id, 0);
2189 TDM_ERR("add fb failed: %m");
2190 free(display_buffer);
2192 *err = TDM_ERROR_OPERATION_FAILED;
2196 TDM_DBG("nexell_data->drm_fd : %d, display_buffer->fb_id:%u", nexell_data->drm_fd,
2197 display_buffer->fb_id);
2199 if (IS_RGB(display_buffer->format))
2200 display_buffer->width = display_buffer->pitches[0] >> 2;
2202 display_buffer->width = display_buffer->pitches[0];
2204 LIST_ADDTAIL(&display_buffer->link, &nexell_data->buffer_list);
2207 *err = TDM_ERROR_NONE;
2209 return display_buffer;
2213 tdm_nexell_data_destroy_buffer_list(tdm_nexell_data *nexell_data)
2215 tdm_nexell_display_buffer *b = NULL, *bb = NULL;
2217 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &nexell_data->buffer_list, link) {
2218 tdm_buffer_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data);
2219 _tdm_nexell_display_cb_destroy_buffer(b->buffer, nexell_data);
2224 nexell_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
2226 tdm_nexell_layer_data *layer_data = layer;
2227 tdm_nexell_data *nexell_data;
2228 tdm_nexell_display_buffer *display_buffer;
2229 tdm_error err = TDM_ERROR_NONE;
2231 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
2232 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
2234 nexell_data = layer_data->nexell_data;
2235 display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer);
2236 if (!display_buffer) {
2237 display_buffer = _tdm_nexell_display_create_buffer(nexell_data, buffer, &err);
2238 RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
2241 if (layer_data->display_buffer != display_buffer) {
2242 if (layer_data->display_buffer)
2243 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
2245 layer_data->display_buffer = display_buffer;
2246 tbm_surface_internal_ref(layer_data->display_buffer->buffer);
2247 layer_data->display_buffer_changed = 1;
2250 return TDM_ERROR_NONE;
2254 nexell_layer_unset_buffer(tdm_layer *layer)
2256 tdm_nexell_layer_data *layer_data = layer;
2258 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
2260 if (!(layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) {
2261 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
2262 layer_data->display_buffer = NULL;
2265 layer_data->display_buffer_changed = 1;
2267 return TDM_ERROR_NONE;
2270 tdm_nexell_layer_data *
2271 nexell_output_data_get_layer_data(tdm_nexell_output_data *output_data, int layer_zpos)
2273 tdm_nexell_layer_data *l = NULL;
2275 RETURN_VAL_IF_FAIL(output_data, NULL);
2277 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
2278 if (l->zpos == layer_zpos)