5 #include <drm_fourcc.h>
6 #include <tdm_helper.h>
8 #include "tdm_nexell.h"
9 #include "tdm_nexell_pp.h"
13 static drmModeModeInfoPtr
14 _tdm_nexell_display_get_mode(tdm_nexell_output_data *output_data)
18 if (!output_data->current_mode) {
19 TDM_ERR("no output_data->current_mode");
23 for (i = 0; i < output_data->count_modes; i++) {
24 drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i];
25 if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) &&
26 (drm_mode->vdisplay == output_data->current_mode->vdisplay) &&
27 (drm_mode->vrefresh == output_data->current_mode->vrefresh) &&
28 (drm_mode->flags == output_data->current_mode->flags) &&
29 (drm_mode->type == output_data->current_mode->type) &&
30 !(strncmp(drm_mode->name, output_data->current_mode->name, TDM_NAME_LEN)))
38 _tdm_nexell_display_to_tdm_mode(drmModeModeInfoPtr drm_mode,
39 tdm_output_mode *tdm_mode)
41 tdm_mode->clock = drm_mode->clock;
42 tdm_mode->hdisplay = drm_mode->hdisplay;
43 tdm_mode->hsync_start = drm_mode->hsync_start;
44 tdm_mode->hsync_end = drm_mode->hsync_end;
45 tdm_mode->htotal = drm_mode->htotal;
46 tdm_mode->hskew = drm_mode->hskew;
47 tdm_mode->vdisplay = drm_mode->vdisplay;
48 tdm_mode->vsync_start = drm_mode->vsync_start;
49 tdm_mode->vsync_end = drm_mode->vsync_end;
50 tdm_mode->vtotal = drm_mode->vtotal;
51 tdm_mode->vscan = drm_mode->vscan;
52 tdm_mode->vrefresh = drm_mode->vrefresh;
53 tdm_mode->flags = drm_mode->flags;
54 tdm_mode->type = drm_mode->type;
55 snprintf(tdm_mode->name, TDM_NAME_LEN, "%s", drm_mode->name);
59 _tdm_nexell_display_get_cur_msc (int fd, int pipe, uint *msc)
63 vbl.request.type = DRM_VBLANK_RELATIVE;
65 vbl.request.type |= DRM_VBLANK_SECONDARY;
67 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
69 vbl.request.sequence = 0;
70 if (drmWaitVBlank(fd, &vbl)) {
71 TDM_ERR("get vblank counter failed: %m");
73 return TDM_ERROR_OPERATION_FAILED;
76 *msc = vbl.reply.sequence;
78 return TDM_ERROR_NONE;
82 _tdm_nexell_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
86 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
88 vbl.request.type |= DRM_VBLANK_SECONDARY;
90 vbl.request.type |= pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
92 vbl.request.sequence = *target_msc;
93 vbl.request.signal = (unsigned long)(uintptr_t)data;
95 if (drmWaitVBlank(fd, &vbl)) {
96 TDM_ERR("wait vblank failed: %m");
98 return TDM_ERROR_OPERATION_FAILED;
101 *target_msc = vbl.reply.sequence;
103 return TDM_ERROR_NONE;
107 _tdm_nexell_display_set_fb(tdm_nexell_data *nexell_data, tbm_surface_h buffer, unsigned int *id)
112 unsigned int handles[4] = {0,};
113 unsigned int pitches[4] = {0,};
114 unsigned int offsets[4] = {0,};
119 width = tbm_surface_get_width(buffer);
120 height = tbm_surface_get_height(buffer);
121 format = tbm_surface_get_format(buffer);
122 count = tbm_surface_internal_get_num_bos(buffer);
123 for (i = 0; i < count; i++) {
124 tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
125 handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
127 count = tbm_surface_internal_get_num_planes(format);
128 for (i = 0; i < count; i++)
129 tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
131 TDM_DBG("AddFB2: drm_fd(%d) size(%dx%d) format(%c%c%c%c) handles(%d,%d,%d) pitches(%d,%d,%d) offsets(%d,%d,%d) buffer(%p)",
132 nexell_data->drm_fd, width, height, FOURCC_STR(format),
133 handles[0], handles[1], handles[2], pitches[0], pitches[1], pitches[2],
134 offsets[0], offsets[1], offsets[2], buffer);
136 ret = drmModeAddFB2(nexell_data->drm_fd, width, height, format,
137 handles, pitches, offsets, &fb_id, 0);
139 TDM_ERR("add fb failed: %m");
140 return TDM_ERROR_OPERATION_FAILED;
142 TDM_DBG("AddFB2 success: drm_fd(%d) fb_id(%u)", nexell_data->drm_fd, fb_id);
145 return TDM_ERROR_NONE;
149 _tdm_nexell_output_update_status(tdm_nexell_output_data *output_data,
150 tdm_output_conn_status status)
152 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
154 if (output_data->status == status)
155 return TDM_ERROR_NONE;
157 output_data->status = status;
159 if (output_data->status_func)
160 output_data->status_func(output_data, status,
161 output_data->status_user_data);
163 return TDM_ERROR_NONE;
167 _tdm_nexell_display_set_crtc(tdm_nexell_data *nexell_data, tdm_nexell_output_data *output_data, int set)
171 output_data->mode_changed = 0;
174 tbm_surface_h buffer = NULL;
175 tbm_surface_info_s info;
176 drmModeModeInfoPtr mode;
177 unsigned int fb_id = 0;
179 if (!output_data->current_mode)
180 return TDM_ERROR_OPERATION_FAILED;
182 mode = _tdm_nexell_display_get_mode(output_data);
184 TDM_ERR("couldn't find proper mode");
185 return TDM_ERROR_BAD_REQUEST;
188 /* A buffer which is set to crtc should has TBM_BO_SCANOUT flag */
189 buffer = tbm_surface_internal_create_with_flags(output_data->current_mode->hdisplay,
190 output_data->current_mode->vdisplay,
191 TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
192 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_OPERATION_FAILED);
194 if (tbm_surface_map(buffer, TBM_SURF_OPTION_WRITE, &info) != TBM_ERROR_NONE) {
195 tbm_surface_destroy(buffer);
196 return TDM_ERROR_OPERATION_FAILED;
198 memset(info.planes[0].ptr, 0x0, info.size);
200 tbm_surface_unmap(buffer);
202 if (_tdm_nexell_display_set_fb(nexell_data, buffer, &fb_id) != TDM_ERROR_NONE) {
203 tbm_surface_destroy(buffer);
204 return TDM_ERROR_OPERATION_FAILED;
207 TDM_DBG("drmModeSetCrtc drm_fd(%d) crtc_id(%u) fb_id(%u) mode(%u,%u)",
208 nexell_data->drm_fd, output_data->crtc_id, fb_id,
209 mode->hdisplay, mode->vdisplay);
211 if (drmModeSetCrtc(nexell_data->drm_fd, output_data->crtc_id,
213 &output_data->connector_id, 1, mode)) {
214 TDM_ERR("set crtc failed: %m");
215 ret = drmModeRmFB(nexell_data->drm_fd, fb_id);
217 TDM_ERR("rm fb failed fb_id(%u)", fb_id);
218 tbm_surface_destroy(buffer);
219 return TDM_ERROR_OPERATION_FAILED;
222 _tdm_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
224 if (output_data->crtc_buffer) {
225 ret = drmModeRmFB(nexell_data->drm_fd, output_data->crtc_fb_id);
227 TDM_ERR("rm fb failed fb_id(%u)", output_data->crtc_fb_id);
228 tbm_surface_destroy(output_data->crtc_buffer);
231 output_data->crtc_buffer = buffer;
232 output_data->crtc_fb_id = fb_id;
234 TDM_DBG("drmModeSetCrtc unset drm_fd(%d) crtc_id(%u)",
235 nexell_data->drm_fd, output_data->crtc_id);
237 if (drmModeSetCrtc(nexell_data->drm_fd, output_data->crtc_id,
238 0, 0, 0, NULL, 0, NULL)) {
239 TDM_ERR("unset crtc failed: %m");
240 return TDM_ERROR_OPERATION_FAILED;
243 if (output_data->crtc_buffer) {
244 ret = drmModeRmFB(nexell_data->drm_fd, output_data->crtc_fb_id);
246 TDM_ERR("rm fb failed fb_id(%u)", output_data->crtc_fb_id);
247 tbm_surface_destroy(output_data->crtc_buffer);
249 output_data->crtc_buffer = NULL;
250 output_data->crtc_fb_id = 0;
253 return TDM_ERROR_NONE;
257 _tdm_nexell_display_commit_layer(tdm_nexell_layer_data *layer_data)
259 tdm_nexell_data *nexell_data = layer_data->nexell_data;
260 tdm_nexell_output_data *output_data = layer_data->output_data;
261 uint32_t fx, fy, fw, fh;
264 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
265 return TDM_ERROR_NONE;
267 // set crtc if crtc is not available and if mode is changed.
268 if (!output_data->crtc_enabled || output_data->mode_changed) {
269 if (_tdm_nexell_display_set_crtc(nexell_data, output_data, 1) != TDM_ERROR_NONE)
270 return TDM_ERROR_OPERATION_FAILED;
272 output_data->crtc_enabled = 1;
274 return TDM_ERROR_NONE;
277 // check if the crtc is available
278 if (output_data->current_mode)
279 crtc_w = output_data->current_mode->hdisplay;
281 drmModeCrtcPtr crtc = drmModeGetCrtc(nexell_data->drm_fd, output_data->crtc_id);
283 TDM_ERR("getting crtc failed");
284 return TDM_ERROR_OPERATION_FAILED;
286 crtc_w = crtc->width;
288 TDM_ERR("getting crtc width failed");
289 drmModeFreeCrtc(crtc);
290 return TDM_ERROR_OPERATION_FAILED;
292 drmModeFreeCrtc(crtc);
295 // reset the changed flags
296 layer_data->display_buffer_changed = 0;
297 layer_data->info_changed = 0;
299 if (layer_data->display_buffer) { // set plane
300 /* Source values are 16.16 fixed point */
301 fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
302 fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
303 fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
304 fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
306 TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
307 layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
308 layer_data->display_buffer->fb_id,
309 layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
310 layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
311 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
312 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
314 if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
315 output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
316 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
317 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
318 fx, fy, fw, fh) < 0) {
319 TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
320 return TDM_ERROR_OPERATION_FAILED;
322 } else { // unset plane
323 TDM_DBG("plane(%d) crtc(%d) pos(%d) : unset plane\n",
324 layer_data->plane_id, output_data->crtc_id, layer_data->zpos);
326 if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
327 output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
328 TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
331 return TDM_ERROR_NONE;
335 _tdm_nexell_display_cb_event(int fd, unsigned int sequence,
336 unsigned int tv_sec, unsigned int tv_usec,
339 tdm_nexell_event_data *event_data = user_data;
340 tdm_nexell_output_data *output_data;
341 tdm_nexell_hwc_data *hwc_data;
344 TDM_ERR("no event data");
348 output_data = event_data->output_data;
350 switch (event_data->type) {
351 case TDM_NEXELL_EVENT_TYPE_PAGEFLIP:
352 if (output_data->commit_func)
353 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
354 event_data->user_data);
356 case TDM_NEXELL_EVENT_TYPE_WAIT:
357 if (output_data->vblank_func)
358 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
359 event_data->user_data);
361 case TDM_NEXELL_EVENT_TYPE_COMMIT:
362 if (output_data->hwc_enable) {
363 hwc_data = output_data->hwc_data;
365 TDM_ERR("no hwc_data");
369 TDM_DBG("crtc_enable(%d), mode_changed(%d)\n", output_data->crtc_enabled, output_data->mode_changed);
371 if (hwc_data->commit_func)
372 hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec,
373 event_data->user_data);
375 if (output_data->commit_func)
376 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
377 event_data->user_data);
388 _tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data)
390 tdm_nexell_output_data *output_data = NULL;
393 if (LIST_IS_EMPTY(&nexell_data->output_list)) {
394 TDM_ERR("no output");
395 return TDM_ERROR_OPERATION_FAILED;
398 /* The TDM drm backend only support one output. */
399 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
403 if (nexell_data->plane_res->count_planes == 0) {
404 TDM_ERR("no layer error");
405 return TDM_ERROR_OPERATION_FAILED;
408 for (i = 0; i < nexell_data->plane_res->count_planes; i++) {
409 tdm_nexell_layer_data *layer_data;
410 drmModePlanePtr plane;
412 plane = drmModeGetPlane(nexell_data->drm_fd, nexell_data->plane_res->planes[i]);
418 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
419 drmModeFreePlane(plane);
423 layer_data = calloc(1, sizeof(tdm_nexell_layer_data));
425 TDM_ERR("alloc failed");
426 drmModeFreePlane(plane);
430 layer_data->nexell_data = nexell_data;
431 layer_data->output_data = output_data;
432 layer_data->plane_id = nexell_data->plane_res->planes[i];
434 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
435 TDM_LAYER_CAPABILITY_GRAPHIC;
436 output_data->primary_layer = layer_data;
438 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
439 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
440 layer_data->capabilities);
442 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
444 drmModeFreePlane(plane);
446 /* can't take care of other planes for various hardware devices */
450 return TDM_ERROR_NONE;
453 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
456 _tdm_nexell_display_get_property(tdm_nexell_data *nexell_data,
457 unsigned int obj_id, unsigned int obj_type,
458 const char *name, unsigned int *value,
461 drmModeObjectPropertiesPtr props = NULL;
464 props = drmModeObjectGetProperties(nexell_data->drm_fd, obj_id, obj_type);
466 return TDM_ERROR_OPERATION_FAILED;
468 for (i = 0; i < props->count_props; i++) {
469 drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd,
475 if (!strcmp(prop->name, name)) {
477 *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
479 *value = (unsigned int)props->prop_values[i];
480 drmModeFreeProperty(prop);
481 drmModeFreeObjectProperties(props);
482 return TDM_ERROR_NONE;
485 drmModeFreeProperty(prop);
487 drmModeFreeObjectProperties(props);
488 TDM_DBG("coundn't find '%s' property", name);
489 return TDM_ERROR_OPERATION_FAILED;
493 _tdm_nexell_display_create_layer_list_type(tdm_nexell_data *nexell_data)
495 tdm_nexell_output_data *output_data = NULL;
496 drmModePlanePtr *planes = NULL;
497 unsigned int *types = NULL;
498 unsigned int type = 0;
499 int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt;
500 int opos_next, cpos_next;
504 if (LIST_IS_EMPTY(&nexell_data->output_list)) {
505 TDM_ERR("no output");
506 return TDM_ERROR_OPERATION_FAILED;
509 /* The TDM drm backend only support one output. */
510 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
514 ret = _tdm_nexell_display_get_property(nexell_data,
515 nexell_data->plane_res->planes[0],
516 DRM_MODE_OBJECT_PLANE, "type", &type,
518 if (ret != TDM_ERROR_NONE) {
519 TDM_ERR("plane doesn't have 'type' property. Call a fallback function");
521 /* if a plane doesn't have "type" property, we call a fallback function
524 return _tdm_nexell_display_create_layer_list(nexell_data);
527 planes = calloc(nexell_data->plane_res->count_planes, sizeof(drmModePlanePtr));
529 TDM_ERR("alloc failed");
533 types = calloc(nexell_data->plane_res->count_planes, sizeof(unsigned int));
535 TDM_ERR("alloc failed");
540 for (i = 0; i < nexell_data->plane_res->count_planes; i++) {
541 drmModePlanePtr plane;
543 plane = drmModeGetPlane(nexell_data->drm_fd, nexell_data->plane_res->planes[i]);
545 TDM_ERR("no plane(%d)", nexell_data->plane_res->planes[i]);
549 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
550 drmModeFreePlane(plane);
554 ret = _tdm_nexell_display_get_property(nexell_data,
555 nexell_data->plane_res->planes[i],
556 DRM_MODE_OBJECT_PLANE, "type", &type,
558 if (ret != TDM_ERROR_NONE) {
559 drmModeFreePlane(plane);
560 TDM_ERR("plane(%d) doesn't have 'type' info",
561 nexell_data->plane_res->planes[i]);
565 planes[plane_cnt] = plane;
566 types[plane_cnt] = type;
570 primary_cnt = ovl_cnt = cursor_cnt = 0;
571 for (i = 0; i < plane_cnt; i++) {
572 if (types[i] == DRM_PLANE_TYPE_CURSOR)
574 else if (types[i] == DRM_PLANE_TYPE_OVERLAY)
576 else if (types[i] == DRM_PLANE_TYPE_PRIMARY)
579 TDM_ERR("invalid type(%d)", types[i]);
582 if (primary_cnt != 1) {
583 TDM_ERR("primary layer count(%d) should be one", primary_cnt);
590 TDM_ERR("plane count(%d) should be over 1", plane_cnt);
594 for (i = plane_cnt - 1; i >= 0; i--) {
595 tdm_nexell_layer_data *layer_data;
597 layer_data = calloc(1, sizeof(tdm_nexell_layer_data));
599 TDM_ERR("alloc failed");
603 layer_data->nexell_data = nexell_data;
604 layer_data->output_data = output_data;
605 layer_data->plane_id = planes[i]->plane_id;
607 if (types[i] == DRM_PLANE_TYPE_CURSOR) {
608 layer_data->capabilities = TDM_LAYER_CAPABILITY_CURSOR |
609 TDM_LAYER_CAPABILITY_GRAPHIC |
610 TDM_LAYER_CAPABILITY_SCANOUT;
611 layer_data->zpos = cpos_next++;
612 TDM_INFO("layer_data(%p): cursor zpos(%d)", layer_data, layer_data->zpos);
613 } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
614 if (opos_next == 0) {
615 layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
616 TDM_LAYER_CAPABILITY_SCALE |
617 TDM_LAYER_CAPABILITY_SCANOUT;
619 layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
620 TDM_LAYER_CAPABILITY_GRAPHIC |
621 TDM_LAYER_CAPABILITY_RESEVED_MEMORY |
622 TDM_LAYER_CAPABILITY_SCANOUT;
624 if (opos_next == 1) {
625 layer_data->zpos = 2;
628 layer_data->zpos = opos_next++;
631 TDM_INFO("layer_data(%p): overlay zpos(%d)", layer_data, layer_data->zpos);
632 } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
633 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
634 TDM_LAYER_CAPABILITY_GRAPHIC |
635 TDM_LAYER_CAPABILITY_RESEVED_MEMORY |
636 TDM_LAYER_CAPABILITY_SCANOUT;
637 layer_data->zpos = 1;
638 output_data->primary_layer = layer_data;
640 TDM_INFO("layer_data(%p): primary zpos(%d)", layer_data, layer_data->zpos);
646 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
647 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
648 layer_data->zpos, layer_data->capabilities);
650 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
653 for (i = 0; i < plane_cnt; i++)
655 drmModeFreePlane(planes[i]);
660 return TDM_ERROR_NONE;
664 for (i = 0; i < nexell_data->plane_res->count_planes; i++)
666 drmModeFreePlane(planes[i]);
672 return TDM_ERROR_OPERATION_FAILED;
677 tdm_nexell_display_create_layer_list(tdm_nexell_data *nexell_data)
679 tdm_nexell_output_data *output_data = NULL;
682 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
683 if (nexell_data->has_universal_plane)
684 ret = _tdm_nexell_display_create_layer_list_type(nexell_data);
687 ret = _tdm_nexell_display_create_layer_list(nexell_data);
689 if (ret != TDM_ERROR_NONE)
692 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
693 if (!output_data->primary_layer) {
694 TDM_ERR("output(%d) no primary layer", output_data->pipe);
695 return TDM_ERROR_OPERATION_FAILED;
699 return TDM_ERROR_NONE;
703 tdm_nexell_display_destroy_output_list(tdm_nexell_data *nexell_data)
705 tdm_nexell_output_data *o = NULL, *oo = NULL;
706 tdm_nexell_hwc_data *hwc_data = NULL;
708 if (LIST_IS_EMPTY(&nexell_data->output_list))
711 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &nexell_data->output_list, link) {
712 hwc_data = o->hwc_data;
713 if (hwc_data && hwc_data->target_hwc_window)
714 nexell_hwc_window_destroy(hwc_data->target_hwc_window);
716 if (o->crtc_enabled) {
717 _tdm_nexell_display_set_crtc(nexell_data, o, 0);
722 if (!LIST_IS_EMPTY(&o->layer_list)) {
723 tdm_nexell_layer_data *l = NULL, *ll = NULL;
724 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
726 if (l->display_buffer)
727 tbm_surface_internal_unref(l->display_buffer->buffer);
732 free(o->output_modes);
738 tdm_nexell_display_update_output_status(tdm_nexell_data *nexell_data)
740 tdm_nexell_output_data *output_data = NULL;
742 if (LIST_IS_EMPTY(&nexell_data->output_list))
745 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
746 drmModeConnectorPtr connector;
747 tdm_output_conn_status new_status;
749 connector = drmModeGetConnector(nexell_data->drm_fd,
750 output_data->connector_id);
752 TDM_ERR("no connector: %d", output_data->connector_id);
756 if (connector->connection == DRM_MODE_CONNECTED)
757 new_status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
759 new_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
761 _tdm_nexell_output_update_status(output_data, new_status);
763 drmModeFreeConnector(connector);
768 tdm_nexell_display_create_output_list(tdm_nexell_data *nexell_data)
770 tdm_nexell_output_data *output_data;
774 drmModeConnectorPtr connector;
775 drmModeEncoderPtr encoder;
777 int hdmia_idx = -1, hdmib_idx = -1;
778 int crtc_id = 0, c, j;
780 RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&nexell_data->output_list),
781 TDM_ERROR_OPERATION_FAILED);
783 /* check if there is a connected output */
784 for (i = 0; i < nexell_data->mode_res->count_connectors; i++) {
785 connector = drmModeGetConnector(nexell_data->drm_fd,
786 nexell_data->mode_res->connectors[i]);
788 TDM_ERR("no connector");
789 return TDM_ERROR_OPERATION_FAILED;
792 /* The TDM drm backend considers only 1 connector because it is the TDM
793 * reference backend and can't take care of all hardware devices.
794 * To support various connectors, planes and crtcs, the new TDM backend
795 * should be implemented.
797 if (connector->connection == DRM_MODE_CONNECTED) {
799 drmModeFreeConnector(connector);
803 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
805 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
808 drmModeFreeConnector(connector);
811 /* use the hdmi connector if there is no connected connector. */
812 /* if there is no hdmi connector, use first connector. */
813 if (conn_idx == -1) {
815 conn_idx = hdmia_idx;
816 else if (hdmib_idx != -1)
817 conn_idx = hdmib_idx;
822 /* The TDM drm backend considers only 1 connector because it is the TDM
823 * reference backend and can't take care of all hardware devices.
824 * To support various connectors, planes and crtcs, the new TDM backend
825 * should be implemented.
827 connector = drmModeGetConnector(nexell_data->drm_fd,
828 nexell_data->mode_res->connectors[conn_idx]);
830 TDM_ERR("no connector");
831 ret = TDM_ERROR_OPERATION_FAILED;
835 if (connector->count_encoders != 1) {
836 TDM_ERR("too many encoders: %d", connector->count_encoders);
837 drmModeFreeConnector(connector);
838 ret = TDM_ERROR_OPERATION_FAILED;
842 encoder = drmModeGetEncoder(nexell_data->drm_fd, connector->encoders[0]);
844 TDM_ERR("no encoder");
845 drmModeFreeConnector(connector);
846 ret = TDM_ERROR_OPERATION_FAILED;
850 for (c = 0; c < nexell_data->mode_res->count_crtcs; c++) {
851 if ((encoder->possible_crtcs & (1 << c)) == 0)
854 crtc_id = nexell_data->mode_res->crtcs[c];
855 allocated |= (1 << c);
860 TDM_ERR("no possible crtc");
861 drmModeFreeConnector(connector);
862 drmModeFreeEncoder(encoder);
863 ret = TDM_ERROR_OPERATION_FAILED;
867 output_data = calloc(1, sizeof(tdm_nexell_output_data));
869 TDM_ERR("alloc failed");
870 drmModeFreeConnector(connector);
871 drmModeFreeEncoder(encoder);
872 ret = TDM_ERROR_OUT_OF_MEMORY;
876 LIST_INITHEAD(&output_data->layer_list);
878 output_data->nexell_data = nexell_data;
879 output_data->connector_id = nexell_data->mode_res->connectors[conn_idx];
880 output_data->encoder_id = encoder->encoder_id;
881 output_data->crtc_id = crtc_id;
882 output_data->pipe = c;
883 output_data->connector_type = connector->connector_type;
884 output_data->connector_type_id = connector->connector_type_id;
886 if (connector->connection == DRM_MODE_CONNECTED)
887 output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
889 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
891 for (j = 0; j < connector->count_props; j++) {
892 drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd,
893 connector->props[j]);
896 if (!strcmp(prop->name, "DPMS")) {
897 output_data->dpms_prop_id = connector->props[j];
898 drmModeFreeProperty(prop);
901 drmModeFreeProperty(prop);
904 if (output_data->dpms_prop_id == 0)
905 TDM_WRN("not support DPMS");
907 output_data->count_modes = connector->count_modes;
908 output_data->drm_modes = calloc(connector->count_modes,
909 sizeof(drmModeModeInfo));
910 if (!output_data->drm_modes) {
911 TDM_ERR("alloc failed");
913 drmModeFreeConnector(connector);
914 drmModeFreeEncoder(encoder);
915 ret = TDM_ERROR_OUT_OF_MEMORY;
918 output_data->output_modes = calloc(connector->count_modes,
919 sizeof(tdm_output_mode));
920 if (!output_data->output_modes) {
921 TDM_ERR("alloc failed");
922 free(output_data->drm_modes);
924 drmModeFreeConnector(connector);
925 drmModeFreeEncoder(encoder);
926 ret = TDM_ERROR_OUT_OF_MEMORY;
929 for (j = 0; j < connector->count_modes; j++) {
930 output_data->drm_modes[j] = connector->modes[j];
931 _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[j],
932 &output_data->output_modes[j]);
935 if (nexell_data->hwc_mode)
936 output_data->hwc_enable = 1;
938 LIST_ADDTAIL(&output_data->link, &nexell_data->output_list);
940 TDM_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
941 output_data, output_data->connector_id, output_data->status,
942 output_data->connector_type,
943 output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
944 output_data->pipe, output_data->dpms_prop_id);
946 drmModeFreeEncoder(encoder);
947 drmModeFreeConnector(connector);
949 TDM_DBG("output count: %d", nexell_data->mode_res->count_connectors);
951 return TDM_ERROR_NONE;
953 tdm_nexell_display_destroy_output_list(nexell_data);
958 nexell_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
960 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
962 caps->max_layer_count = -1; /* not defined */
964 return TDM_ERROR_NONE;
968 nexell_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps)
970 return tdm_nexell_pp_get_capability(bdata, caps);
974 nexell_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
976 tdm_nexell_data *nexell_data = bdata;
977 tdm_nexell_output_data *output_data = NULL;
978 tdm_output **outputs;
982 RETURN_VAL_IF_FAIL(nexell_data, NULL);
983 RETURN_VAL_IF_FAIL(count, NULL);
986 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link)
990 ret = TDM_ERROR_NONE;
994 /* will be freed in frontend */
995 outputs = calloc(*count, sizeof(tdm_nexell_output_data *));
997 TDM_ERR("failed: alloc memory");
999 ret = TDM_ERROR_OUT_OF_MEMORY;
1004 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link)
1005 outputs[i++] = output_data;
1008 *error = TDM_ERROR_NONE;
1018 nexell_display_get_fd(tdm_backend_data *bdata, int *fd)
1020 tdm_nexell_data *nexell_data = bdata;
1022 RETURN_VAL_IF_FAIL(nexell_data, TDM_ERROR_INVALID_PARAMETER);
1023 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
1025 *fd = nexell_data->drm_fd;
1027 return TDM_ERROR_NONE;
1031 nexell_display_handle_events(tdm_backend_data *bdata)
1033 tdm_nexell_data *nexell_data = bdata;
1034 drmEventContext ctx;
1036 RETURN_VAL_IF_FAIL(nexell_data, TDM_ERROR_INVALID_PARAMETER);
1038 memset(&ctx, 0, sizeof(drmEventContext));
1040 ctx.version = DRM_EVENT_CONTEXT_VERSION;
1041 ctx.page_flip_handler = _tdm_nexell_display_cb_event;
1042 ctx.vblank_handler = _tdm_nexell_display_cb_event;
1044 drmHandleEvent(nexell_data->drm_fd, &ctx);
1046 return TDM_ERROR_NONE;
1050 nexell_display_create_pp(tdm_backend_data *bdata, tdm_error *error)
1052 tdm_nexell_data *nexell_data = bdata;
1054 RETURN_VAL_IF_FAIL(nexell_data, NULL);
1056 return tdm_nexell_pp_create(nexell_data, error);
1060 nexell_output_get_capability(tdm_output *output, tdm_caps_output *caps)
1062 tdm_nexell_output_data *output_data = output;
1063 tdm_nexell_data *nexell_data;
1064 drmModeConnectorPtr connector = NULL;
1065 drmModeCrtcPtr crtc = NULL;
1066 drmModeObjectPropertiesPtr props = NULL;
1070 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1071 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1073 memset(caps, 0, sizeof(tdm_caps_output));
1075 nexell_data = output_data->nexell_data;
1077 snprintf(caps->maker, TDM_NAME_LEN, "unknown");
1078 snprintf(caps->model, TDM_NAME_LEN, "unknown");
1079 snprintf(caps->name, TDM_NAME_LEN, "unknown");
1081 caps->status = output_data->status;
1082 caps->type = output_data->connector_type;
1083 caps->type_id = output_data->connector_type_id;
1085 connector = drmModeGetConnector(nexell_data->drm_fd, output_data->connector_id);
1086 RETURN_VAL_IF_FAIL(connector, TDM_ERROR_OPERATION_FAILED);
1088 caps->mode_count = connector->count_modes;
1089 caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count);
1091 ret = TDM_ERROR_OUT_OF_MEMORY;
1092 TDM_ERR("alloc failed\n");
1096 if (caps->mode_count != output_data->count_modes) {
1097 drmModeModeInfoPtr new_drm_modes;
1098 tdm_output_mode *new_output_modes;
1100 new_drm_modes = calloc(connector->count_modes,
1101 sizeof(drmModeModeInfo));
1102 if (!new_drm_modes) {
1103 ret = TDM_ERROR_OUT_OF_MEMORY;
1104 TDM_ERR("alloc failed drm_modes\n");
1107 new_output_modes = calloc(connector->count_modes,
1108 sizeof(tdm_output_mode));
1109 if (!new_output_modes) {
1110 ret = TDM_ERROR_OUT_OF_MEMORY;
1111 TDM_ERR("alloc failed output_modes\n");
1112 free(new_drm_modes);
1115 free(output_data->drm_modes);
1116 free(output_data->output_modes);
1118 output_data->drm_modes = new_drm_modes;
1119 output_data->output_modes = new_output_modes;
1120 output_data->count_modes = caps->mode_count;
1123 for (i = 0; i < caps->mode_count; i++) {
1124 output_data->drm_modes[i] = connector->modes[i];
1125 _tdm_nexell_display_to_tdm_mode(&output_data->drm_modes[i],
1126 &output_data->output_modes[i]);
1127 caps->modes[i] = output_data->output_modes[i];
1130 caps->mmWidth = connector->mmWidth;
1131 caps->mmHeight = connector->mmHeight;
1132 caps->subpixel = connector->subpixel;
1134 caps->min_w = nexell_data->mode_res->min_width;
1135 caps->min_h = nexell_data->mode_res->min_height;
1136 caps->max_w = nexell_data->mode_res->max_width;
1137 caps->max_h = nexell_data->mode_res->max_height;
1138 caps->preferred_align = -1;
1140 crtc = drmModeGetCrtc(nexell_data->drm_fd, output_data->crtc_id);
1142 ret = TDM_ERROR_OPERATION_FAILED;
1143 TDM_ERR("get crtc failed: %m\n");
1147 props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->crtc_id,
1148 DRM_MODE_OBJECT_CRTC);
1150 ret = TDM_ERROR_OPERATION_FAILED;
1151 TDM_ERR("get crtc properties failed: %m\n");
1155 caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
1157 ret = TDM_ERROR_OUT_OF_MEMORY;
1158 TDM_ERR("alloc failed\n");
1162 caps->prop_count = 0;
1163 for (i = 0; i < props->count_props; i++) {
1164 drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, props->props[i]);
1167 snprintf(caps->props[caps->prop_count].name, TDM_NAME_LEN, "%s", prop->name);
1168 caps->props[caps->prop_count].id = props->props[i];
1170 drmModeFreeProperty(prop);
1173 if (output_data->hwc_enable) {
1174 caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
1177 drmModeFreeObjectProperties(props);
1178 drmModeFreeCrtc(crtc);
1179 drmModeFreeConnector(connector);
1181 return TDM_ERROR_NONE;
1183 drmModeFreeCrtc(crtc);
1184 drmModeFreeObjectProperties(props);
1185 drmModeFreeConnector(connector);
1188 memset(caps, 0, sizeof(tdm_caps_output));
1193 nexell_output_get_layers(tdm_output *output, int *count, tdm_error *error)
1195 tdm_nexell_output_data *output_data = output;
1196 tdm_nexell_layer_data *layer_data = NULL;
1201 RETURN_VAL_IF_FAIL(output_data, NULL);
1202 RETURN_VAL_IF_FAIL(count, NULL);
1205 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1208 if (output_data->hwc_enable) {
1210 ret = TDM_ERROR_NONE;
1215 ret = TDM_ERROR_NONE;
1219 /* will be freed in frontend */
1220 layers = calloc(*count, sizeof(tdm_nexell_layer_data *));
1222 TDM_ERR("failed: alloc memory");
1224 ret = TDM_ERROR_OUT_OF_MEMORY;
1229 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1230 layers[i++] = layer_data;
1233 *error = TDM_ERROR_NONE;
1243 nexell_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
1245 tdm_nexell_output_data *output_data = output;
1246 tdm_nexell_data *nexell_data;
1249 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1250 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1252 nexell_data = output_data->nexell_data;
1253 ret = drmModeObjectSetProperty(nexell_data->drm_fd,
1254 output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
1257 TDM_ERR("set property failed: %m");
1258 return TDM_ERROR_OPERATION_FAILED;
1261 return TDM_ERROR_NONE;
1265 nexell_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
1267 tdm_nexell_output_data *output_data = output;
1268 tdm_nexell_data *nexell_data;
1269 drmModeObjectPropertiesPtr props;
1272 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1273 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1274 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1276 nexell_data = output_data->nexell_data;
1277 props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->crtc_id,
1278 DRM_MODE_OBJECT_CRTC);
1279 if (props == NULL) {
1280 TDM_ERR("get property failed: %m");
1281 return TDM_ERROR_OPERATION_FAILED;
1284 for (i = 0; i < props->count_props; i++)
1285 if (props->props[i] == id) {
1286 (*value).u32 = (uint)props->prop_values[i];
1290 drmModeFreeObjectProperties(props);
1292 return TDM_ERROR_NONE;
1296 nexell_output_wait_vblank(tdm_output *output, int interval, int sync,
1299 tdm_nexell_output_data *output_data = output;
1300 tdm_nexell_data *nexell_data;
1301 tdm_nexell_event_data *event_data;
1305 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1307 event_data = calloc(1, sizeof(tdm_nexell_event_data));
1309 TDM_ERR("alloc failed");
1310 return TDM_ERROR_OUT_OF_MEMORY;
1313 nexell_data = output_data->nexell_data;
1315 ret = _tdm_nexell_display_get_cur_msc(nexell_data->drm_fd, output_data->pipe,
1317 if (ret != TDM_ERROR_NONE)
1320 target_msc += interval;
1322 event_data->type = TDM_NEXELL_EVENT_TYPE_WAIT;
1323 event_data->output_data = output_data;
1324 event_data->user_data = user_data;
1326 ret = _tdm_nexell_display_wait_vblank(nexell_data->drm_fd, output_data->pipe,
1327 &target_msc, event_data);
1328 if (ret != TDM_ERROR_NONE)
1331 return TDM_ERROR_NONE;
1338 nexell_output_set_vblank_handler(tdm_output *output,
1339 tdm_output_vblank_handler func)
1341 tdm_nexell_output_data *output_data = output;
1343 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1344 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1346 output_data->vblank_func = func;
1348 return TDM_ERROR_NONE;
1352 nexell_output_commit(tdm_output *output, int sync, void *user_data)
1354 tdm_nexell_output_data *output_data = output;
1355 tdm_nexell_data *nexell_data;
1356 tdm_nexell_layer_data *layer_data = NULL;
1358 int do_waitvblank = 1;
1360 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1362 nexell_data = output_data->nexell_data;
1365 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1366 if (layer_data == output_data->primary_layer) {
1367 ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data,
1369 if (ret != TDM_ERROR_NONE)
1372 ret = _tdm_nexell_display_commit_layer(layer_data);
1373 if (ret != TDM_ERROR_NONE)
1378 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1379 ret = _tdm_nexell_display_commit_layer(layer_data);
1380 if (ret != TDM_ERROR_NONE)
1385 if (do_waitvblank == 1) {
1386 tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
1390 TDM_ERR("alloc failed");
1391 return TDM_ERROR_OUT_OF_MEMORY;
1394 ret = _tdm_nexell_display_get_cur_msc(nexell_data->drm_fd, output_data->pipe,
1396 if (ret != TDM_ERROR_NONE) {
1403 event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
1404 event_data->output_data = output_data;
1405 event_data->user_data = user_data;
1407 ret = _tdm_nexell_display_wait_vblank(nexell_data->drm_fd, output_data->pipe,
1408 &target_msc, event_data);
1409 if (ret != TDM_ERROR_NONE) {
1415 return TDM_ERROR_NONE;
1419 nexell_output_set_commit_handler(tdm_output *output,
1420 tdm_output_commit_handler func)
1422 tdm_nexell_output_data *output_data = output;
1424 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1425 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1427 output_data->commit_func = func;
1429 return TDM_ERROR_NONE;
1433 nexell_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1435 tdm_nexell_output_data *output_data = output;
1436 tdm_nexell_data *nexell_data;
1439 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1441 if (output_data->dpms_prop_id == 0) {
1442 TDM_WRN("not support DPMS");
1443 return TDM_ERROR_OPERATION_FAILED;
1446 nexell_data = output_data->nexell_data;
1447 ret = drmModeObjectSetProperty(nexell_data->drm_fd,
1448 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1449 output_data->dpms_prop_id, dpms_value);
1451 TDM_ERR("set dpms failed: %m");
1452 return TDM_ERROR_OPERATION_FAILED;
1455 return TDM_ERROR_NONE;
1459 nexell_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1461 tdm_nexell_output_data *output_data = output;
1462 tdm_nexell_data *nexell_data;
1463 drmModeObjectPropertiesPtr props;
1466 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1467 RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
1469 nexell_data = output_data->nexell_data;
1470 props = drmModeObjectGetProperties(nexell_data->drm_fd, output_data->connector_id,
1471 DRM_MODE_OBJECT_CONNECTOR);
1472 if (props == NULL) {
1473 TDM_ERR("get property failed: %m");
1474 return TDM_ERROR_OPERATION_FAILED;
1477 for (i = 0; i < props->count_props; i++)
1478 if (props->props[i] == output_data->dpms_prop_id) {
1479 *dpms_value = (uint)props->prop_values[i];
1483 drmModeFreeObjectProperties(props);
1485 return TDM_ERROR_NONE;
1489 nexell_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1491 tdm_nexell_output_data *output_data = output;
1492 tdm_error ret = TDM_ERROR_NONE;
1494 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1495 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1497 /* create or replace the target_window when the output mode is set */
1498 if (output_data->hwc_enable) {
1499 ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
1500 if (ret != TDM_ERROR_NONE) {
1501 TDM_ERR("set info target hwc window failed (%d)", ret);
1506 output_data->current_mode = mode;
1507 output_data->mode_changed = 1;
1509 TDM_INFO("Set the output mode: %s, %d, %d, %d, %d, %d",
1510 mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
1512 return TDM_ERROR_NONE;
1516 nexell_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1518 tdm_nexell_output_data *output_data = output;
1520 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1521 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1523 *mode = output_data->current_mode;
1525 return TDM_ERROR_NONE;
1529 nexell_output_get_hwc(tdm_output *output, tdm_error *error)
1531 tdm_nexell_hwc_data *hwc_data = NULL;
1532 tdm_nexell_output_data *output_data = output;
1533 tdm_error ret = TDM_ERROR_NONE;
1536 TDM_ERR("invalid params");
1538 *error = TDM_ERROR_INVALID_PARAMETER;
1542 if (output_data->hwc_data) {
1543 TDM_INFO("hwc_data already exists");
1545 *error = TDM_ERROR_NONE;
1546 return output_data->hwc_data;
1549 hwc_data = calloc(1, sizeof(tdm_nexell_hwc_data));
1551 TDM_ERR("alloc failed");
1553 *error = TDM_ERROR_OUT_OF_MEMORY;
1556 for (int i = 0; i < NUM_LAYERS; i++) {
1557 hwc_data->ui_buffer_queue[i].tqueue = NULL;
1558 hwc_data->ui_buffer_queue[i].ref_cnt= 0;
1560 hwc_data->output_data = output_data;
1562 LIST_INITHEAD(&hwc_data->hwc_window_list);
1564 output_data->hwc_data = hwc_data;
1566 ret = nexell_hwc_initailize_target_window(output_data->hwc_data);
1567 if (ret != TDM_ERROR_NONE) {
1568 TDM_ERR("create target hwc window failed (%d)", ret);
1576 *error = TDM_ERROR_NONE;
1582 nexell_output_set_status_handler(tdm_output *output,
1583 tdm_output_status_handler func,
1586 tdm_nexell_output_data *output_data = output;
1588 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1589 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1591 output_data->status_func = func;
1592 output_data->status_user_data = user_data;
1594 return TDM_ERROR_NONE;
1598 nexell_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
1600 tdm_nexell_layer_data *layer_data = layer;
1601 tdm_nexell_data *nexell_data;
1602 drmModePlanePtr plane = NULL;
1603 drmModeObjectPropertiesPtr props = NULL;
1604 int i, format_count = 0;
1607 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1608 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1610 memset(caps, 0, sizeof(tdm_caps_layer));
1612 nexell_data = layer_data->nexell_data;
1613 plane = drmModeGetPlane(nexell_data->drm_fd, layer_data->plane_id);
1615 TDM_ERR("get plane failed: %m");
1616 ret = TDM_ERROR_OPERATION_FAILED;
1620 caps->capabilities = layer_data->capabilities;
1621 caps->zpos = layer_data->zpos; /* if VIDEO layer, zpos is -1 */
1623 caps->format_count = plane->count_formats;
1624 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1625 if (!caps->formats) {
1626 ret = TDM_ERROR_OUT_OF_MEMORY;
1627 TDM_ERR("alloc failed\n");
1631 for (i = 0; i < caps->format_count; i++) {
1632 /* TODO: kernel reports wrong formats */
1633 if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
1634 plane->formats[i] != DRM_FORMAT_ARGB8888 &&
1635 plane->formats[i] != DRM_FORMAT_YUV420) {
1636 TDM_WRN("plane(%d) zpos(%d) %c%c%c%c skipped",
1637 layer_data->plane_id, layer_data->zpos, FOURCC_STR(plane->formats[i]));
1640 caps->formats[format_count] = tdm_nexell_format_to_tbm_format(plane->formats[i]);
1644 caps->format_count = format_count;
1646 props = drmModeObjectGetProperties(nexell_data->drm_fd, layer_data->plane_id,
1647 DRM_MODE_OBJECT_PLANE);
1649 ret = TDM_ERROR_OPERATION_FAILED;
1650 TDM_ERR("get plane properties failed: %m\n");
1654 caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
1656 ret = TDM_ERROR_OUT_OF_MEMORY;
1657 TDM_ERR("alloc failed\n");
1661 caps->prop_count = 0;
1662 for (i = 0; i < props->count_props; i++) {
1663 drmModePropertyPtr prop = drmModeGetProperty(nexell_data->drm_fd, props->props[i]);
1666 if (!strncmp(prop->name, "type", TDM_NAME_LEN)) {
1667 drmModeFreeProperty(prop);
1670 if (!strncmp(prop->name, "zpos", TDM_NAME_LEN)) {
1671 drmModeFreeProperty(prop);
1674 snprintf(caps->props[caps->prop_count].name, TDM_NAME_LEN, "%s", prop->name);
1675 caps->props[caps->prop_count].id = props->props[i];
1677 drmModeFreeProperty(prop);
1680 drmModeFreeObjectProperties(props);
1681 drmModeFreePlane(plane);
1683 return TDM_ERROR_NONE;
1685 drmModeFreeObjectProperties(props);
1686 drmModeFreePlane(plane);
1687 free(caps->formats);
1689 memset(caps, 0, sizeof(tdm_caps_layer));
1694 nexell_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1696 tdm_nexell_layer_data *layer_data = layer;
1697 tdm_nexell_data *nexell_data;
1700 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1701 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
1703 nexell_data = layer_data->nexell_data;
1704 ret = drmModeObjectSetProperty(nexell_data->drm_fd,
1705 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
1708 TDM_ERR("set property failed: %m");
1709 return TDM_ERROR_OPERATION_FAILED;
1712 return TDM_ERROR_NONE;
1716 nexell_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1718 tdm_nexell_layer_data *layer_data = layer;
1719 tdm_nexell_data *nexell_data;
1720 drmModeObjectPropertiesPtr props;
1723 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1724 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
1725 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1727 nexell_data = layer_data->nexell_data;
1728 props = drmModeObjectGetProperties(nexell_data->drm_fd, layer_data->plane_id,
1729 DRM_MODE_OBJECT_PLANE);
1730 if (props == NULL) {
1731 TDM_ERR("get property failed: %m");
1732 return TDM_ERROR_OPERATION_FAILED;
1735 for (i = 0; i < props->count_props; i++)
1736 if (props->props[i] == id) {
1737 (*value).u32 = (uint)props->prop_values[i];
1741 drmModeFreeObjectProperties(props);
1743 return TDM_ERROR_NONE;
1747 nexell_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1749 tdm_nexell_layer_data *layer_data = layer;
1751 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1752 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1754 layer_data->info = *info;
1755 layer_data->info_changed = 1;
1757 return TDM_ERROR_NONE;
1761 nexell_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1763 tdm_nexell_layer_data *layer_data = layer;
1765 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1766 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1768 *info = layer_data->info;
1770 return TDM_ERROR_NONE;
1773 static tdm_nexell_display_buffer *
1774 _tdm_nexell_display_find_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer)
1776 tdm_nexell_display_buffer *display_buffer = NULL;
1778 LIST_FOR_EACH_ENTRY(display_buffer, &nexell_data->buffer_list, link) {
1779 if (display_buffer->buffer == buffer)
1780 return display_buffer;
1787 _tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
1789 tdm_nexell_data *nexell_data;
1790 tdm_nexell_display_buffer *display_buffer;
1791 tdm_nexell_layer_data *layer_data = NULL;
1792 tdm_nexell_output_data *output_data = NULL;
1793 char buf[256] = {0,};
1797 TDM_ERR("no user_data");
1801 TDM_ERR("no buffer");
1805 nexell_data = (tdm_nexell_data *) user_data;
1807 display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer);
1808 if (!display_buffer) {
1809 TDM_ERR("no display_buffer");
1813 LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
1814 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1815 if (display_buffer == layer_data->display_buffer)
1816 layer_data->display_buffer = NULL;
1820 if (display_buffer->fb_id > 0) {
1821 if (drmModeRmFB(nexell_data->drm_fd, display_buffer->fb_id) < 0) {
1822 ret_tmp = strerror_r(errno, buf, sizeof(buf));
1823 TDM_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
1827 TDM_DBG("destroy buffer:%p", display_buffer->buffer);
1829 LIST_DEL(&display_buffer->link);
1830 free(display_buffer);
1833 static tdm_nexell_display_buffer *
1834 _tdm_nexell_display_create_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer, tdm_error *err)
1836 tdm_nexell_display_buffer *display_buffer = NULL;
1837 tdm_error res = TDM_ERROR_NONE;
1840 display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer));
1841 if (!display_buffer) {
1842 TDM_ERR("alloc failed");
1844 *err = TDM_ERROR_OUT_OF_MEMORY;
1848 display_buffer->buffer = buffer;
1850 res = tdm_buffer_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data);
1851 if (res != TDM_ERROR_NONE) {
1852 TDM_ERR("add destroy handler fail");
1853 free(display_buffer);
1859 display_buffer->width = tbm_surface_get_width(buffer);
1860 display_buffer->height = tbm_surface_get_height(buffer);
1861 display_buffer->format = tbm_surface_get_format(buffer);
1862 display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
1863 count = tbm_surface_internal_get_num_planes(display_buffer->format);
1864 TDM_DBG(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d",
1865 buffer, display_buffer->width, display_buffer->height,
1866 FOURCC_STR(display_buffer->format), display_buffer->count, count);
1868 for (i = 0; i < count; i++) {
1872 bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i);
1873 bo = tbm_surface_internal_get_bo(buffer, bo_idx);
1874 display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
1876 tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
1877 &display_buffer->offsets[i],
1878 &display_buffer->pitches[i]);
1879 TDM_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)",
1880 i, display_buffer->size, display_buffer->offsets[i],
1881 display_buffer->pitches[i], bo_idx, display_buffer->handles[i]);
1884 ret = drmModeAddFB2(nexell_data->drm_fd, display_buffer->width, display_buffer->height,
1885 display_buffer->format, display_buffer->handles, display_buffer->pitches,
1886 display_buffer->offsets, &display_buffer->fb_id, 0);
1888 TDM_ERR("add fb failed: %m");
1889 free(display_buffer);
1891 *err = TDM_ERROR_OPERATION_FAILED;
1895 TDM_DBG("nexell_data->drm_fd : %d, display_buffer->fb_id:%u", nexell_data->drm_fd,
1896 display_buffer->fb_id);
1898 if (IS_RGB(display_buffer->format))
1899 display_buffer->width = display_buffer->pitches[0] >> 2;
1901 display_buffer->width = display_buffer->pitches[0];
1903 LIST_ADDTAIL(&display_buffer->link, &nexell_data->buffer_list);
1906 *err = TDM_ERROR_NONE;
1908 return display_buffer;
1912 tdm_nexell_data_destroy_buffer_list(tdm_nexell_data *nexell_data)
1914 tdm_nexell_display_buffer *b = NULL, *bb = NULL;
1916 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &nexell_data->buffer_list, link) {
1917 tdm_buffer_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data);
1918 _tdm_nexell_display_cb_destroy_buffer(b->buffer, nexell_data);
1923 nexell_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1925 tdm_nexell_layer_data *layer_data = layer;
1926 tdm_nexell_data *nexell_data;
1927 tdm_nexell_display_buffer *display_buffer;
1928 tdm_error err = TDM_ERROR_NONE;
1930 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1931 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
1933 nexell_data = layer_data->nexell_data;
1934 display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer);
1935 if (!display_buffer) {
1936 display_buffer = _tdm_nexell_display_create_buffer(nexell_data, buffer, &err);
1937 RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
1940 if (layer_data->display_buffer != display_buffer) {
1941 if (layer_data->display_buffer)
1942 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
1944 layer_data->display_buffer = display_buffer;
1945 tbm_surface_internal_ref(layer_data->display_buffer->buffer);
1946 layer_data->display_buffer_changed = 1;
1949 return TDM_ERROR_NONE;
1953 nexell_layer_unset_buffer(tdm_layer *layer)
1955 tdm_nexell_layer_data *layer_data = layer;
1957 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1959 if (!(layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) {
1960 tbm_surface_internal_unref(layer_data->display_buffer->buffer);
1961 layer_data->display_buffer = NULL;
1964 layer_data->display_buffer_changed = 1;
1966 return TDM_ERROR_NONE;
1969 tdm_nexell_layer_data *
1970 nexell_output_data_get_layer_data(tdm_nexell_output_data *output_data, int layer_zpos)
1972 tdm_nexell_layer_data *l = NULL;
1974 RETURN_VAL_IF_FAIL(output_data, NULL);
1976 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
1977 if (l->zpos == layer_zpos)