5 #include <drm_fourcc.h>
6 #include <tdm_helper.h>
9 #include "tdm_drm_pp.h"
13 typedef struct _tdm_drm_output_data tdm_drm_output_data;
14 typedef struct _tdm_drm_layer_data tdm_drm_layer_data;
15 typedef struct _tdm_drm_event_data tdm_drm_event_data;
18 TDM_DRM_EVENT_TYPE_WAIT,
19 TDM_DRM_EVENT_TYPE_COMMIT,
20 TDM_DRM_EVENT_TYPE_PAGEFLIP,
23 typedef struct _tdm_drm_display_buffer {
24 struct list_head link;
29 } tdm_drm_display_buffer;
31 struct _tdm_drm_event_data {
32 tdm_drm_event_type type;
33 tdm_drm_output_data *output_data;
37 struct _tdm_drm_output_data {
38 struct list_head link;
40 /* data which are fixed at initializing */
41 tdm_drm_data *drm_data;
42 uint32_t connector_id;
46 uint32_t dpms_prop_id;
48 drmModeModeInfoPtr drm_modes;
49 tdm_output_mode *output_modes;
50 tdm_output_type connector_type;
51 unsigned int connector_type_id;
52 struct list_head layer_list;
53 tdm_drm_layer_data *primary_layer;
55 /* not fixed data below */
56 tdm_output_vblank_handler vblank_func;
57 tdm_output_commit_handler commit_func;
59 tdm_output_conn_status status;
60 tdm_output_status_handler status_func;
61 void *status_user_data;
64 const tdm_output_mode *current_mode;
67 struct _tdm_drm_layer_data {
68 struct list_head link;
70 /* data which are fixed at initializing */
71 tdm_drm_data *drm_data;
72 tdm_drm_output_data *output_data;
74 tdm_layer_capability capabilities;
77 /* not fixed data below */
81 tdm_drm_display_buffer *display_buffer;
82 int display_buffer_changed;
85 static drmModeModeInfoPtr
86 _tdm_drm_display_get_mode(tdm_drm_output_data *output_data)
90 if (!output_data->current_mode) {
91 TDM_ERR("no output_data->current_mode");
95 for (i = 0; i < output_data->count_modes; i++) {
96 drmModeModeInfoPtr drm_mode = &output_data->drm_modes[i];
97 if ((drm_mode->hdisplay == output_data->current_mode->hdisplay) &&
98 (drm_mode->vdisplay == output_data->current_mode->vdisplay) &&
99 (drm_mode->vrefresh == output_data->current_mode->vrefresh) &&
100 (drm_mode->flags == output_data->current_mode->flags) &&
101 (drm_mode->type == output_data->current_mode->type) &&
102 !(strncmp(drm_mode->name, output_data->current_mode->name, TDM_NAME_LEN)))
109 static tdm_drm_display_buffer *
110 _tdm_drm_display_find_buffer(tdm_drm_data *drm_data, tbm_surface_h buffer)
112 tdm_drm_display_buffer *display_buffer = NULL;
114 LIST_FOR_EACH_ENTRY(display_buffer, &drm_data->buffer_list, link) {
115 if (display_buffer->buffer == buffer)
116 return display_buffer;
123 _tdm_drm_display_to_tdm_mode(drmModeModeInfoPtr drm_mode,
124 tdm_output_mode *tdm_mode)
126 tdm_mode->clock = drm_mode->clock;
127 tdm_mode->hdisplay = drm_mode->hdisplay;
128 tdm_mode->hsync_start = drm_mode->hsync_start;
129 tdm_mode->hsync_end = drm_mode->hsync_end;
130 tdm_mode->htotal = drm_mode->htotal;
131 tdm_mode->hskew = drm_mode->hskew;
132 tdm_mode->vdisplay = drm_mode->vdisplay;
133 tdm_mode->vsync_start = drm_mode->vsync_start;
134 tdm_mode->vsync_end = drm_mode->vsync_end;
135 tdm_mode->vtotal = drm_mode->vtotal;
136 tdm_mode->vscan = drm_mode->vscan;
137 tdm_mode->vrefresh = drm_mode->vrefresh;
138 tdm_mode->flags = drm_mode->flags;
139 tdm_mode->type = drm_mode->type;
140 snprintf(tdm_mode->name, TDM_NAME_LEN, "%s", drm_mode->name);
144 _tdm_drm_display_get_cur_msc (int fd, int pipe, uint *msc)
148 vbl.request.type = DRM_VBLANK_RELATIVE;
150 vbl.request.type |= DRM_VBLANK_SECONDARY;
152 vbl.request.sequence = 0;
153 if (drmWaitVBlank(fd, &vbl)) {
154 TDM_ERR("get vblank counter failed: %m");
156 return TDM_ERROR_OPERATION_FAILED;
159 *msc = vbl.reply.sequence;
161 return TDM_ERROR_NONE;
165 _tdm_drm_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
169 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
171 vbl.request.type |= DRM_VBLANK_SECONDARY;
173 vbl.request.sequence = *target_msc;
174 vbl.request.signal = (unsigned long)(uintptr_t)data;
176 if (drmWaitVBlank(fd, &vbl)) {
178 TDM_ERR("wait vblank failed: %m");
179 return TDM_ERROR_OPERATION_FAILED;
182 *target_msc = vbl.reply.sequence;
184 return TDM_ERROR_NONE;
188 _tdm_drm_output_update_status(tdm_drm_output_data *output_data,
189 tdm_output_conn_status status)
191 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
193 if (output_data->status == status)
194 return TDM_ERROR_NONE;
196 output_data->status = status;
198 if (output_data->status_func)
199 output_data->status_func(output_data, status,
200 output_data->status_user_data);
202 return TDM_ERROR_NONE;
206 _tdm_drm_display_commit_primary_layer(tdm_drm_layer_data *layer_data,
207 void *user_data, int *do_waitvblank)
209 tdm_drm_data *drm_data = layer_data->drm_data;
210 tdm_drm_output_data *output_data = layer_data->output_data;
212 if (output_data->mode_changed && layer_data->display_buffer_changed) {
213 drmModeModeInfoPtr mode;
215 if (!layer_data->display_buffer) {
216 TDM_ERR("primary layer should have a buffer for modestting");
217 return TDM_ERROR_BAD_REQUEST;
220 output_data->mode_changed = 0;
221 layer_data->display_buffer_changed = 0;
222 layer_data->info_changed = 0;
224 mode = _tdm_drm_display_get_mode(output_data);
226 TDM_ERR("couldn't find proper mode");
227 return TDM_ERROR_BAD_REQUEST;
230 if (drmModeSetCrtc(drm_data->drm_fd, output_data->crtc_id,
231 layer_data->display_buffer->fb_id, 0, 0,
232 &output_data->connector_id, 1, mode)) {
233 TDM_ERR("set crtc failed: %m");
234 return TDM_ERROR_OPERATION_FAILED;
237 _tdm_drm_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
240 return TDM_ERROR_NONE;
241 } else if (layer_data->display_buffer_changed) {
242 layer_data->display_buffer_changed = 0;
244 if (!layer_data->display_buffer) {
245 if (drmModeSetCrtc(drm_data->drm_fd, output_data->crtc_id,
246 0, 0, 0, NULL, 0, NULL)) {
247 TDM_ERR("unset crtc failed: %m");
248 return TDM_ERROR_OPERATION_FAILED;
251 if (output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
252 _tdm_drm_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_CONNECTED);
256 tdm_drm_event_data *event_data = calloc(1, sizeof(tdm_drm_event_data));
259 TDM_ERR("alloc failed");
260 return TDM_ERROR_OUT_OF_MEMORY;
263 event_data->type = TDM_DRM_EVENT_TYPE_PAGEFLIP;
264 event_data->output_data = output_data;
265 event_data->user_data = user_data;
266 if (drmModePageFlip(drm_data->drm_fd, output_data->crtc_id,
267 layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) {
268 TDM_ERR("pageflip failed: %m");
270 return TDM_ERROR_OPERATION_FAILED;
276 return TDM_ERROR_NONE;
280 _tdm_drm_display_commit_layer(tdm_drm_layer_data *layer_data)
282 tdm_drm_data *drm_data = layer_data->drm_data;
283 tdm_drm_output_data *output_data = layer_data->output_data;
284 uint32_t fx, fy, fw, fh;
287 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
288 return TDM_ERROR_NONE;
290 if (output_data->current_mode)
291 crtc_w = output_data->current_mode->hdisplay;
293 drmModeCrtcPtr crtc = drmModeGetCrtc(drm_data->drm_fd, output_data->crtc_id);
295 TDM_ERR("getting crtc failed");
296 return TDM_ERROR_OPERATION_FAILED;
298 crtc_w = crtc->width;
300 TDM_ERR("getting crtc width failed");
301 drmModeFreeCrtc(crtc);
302 return TDM_ERROR_OPERATION_FAILED;
304 drmModeFreeCrtc(crtc);
307 layer_data->display_buffer_changed = 0;
308 layer_data->info_changed = 0;
310 if (!layer_data->display_buffer) {
311 if (drmModeSetPlane(drm_data->drm_fd, layer_data->plane_id,
312 output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
313 TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
315 return TDM_ERROR_NONE;
318 /* Source values are 16.16 fixed point */
319 fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
320 fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
321 fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
322 fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
324 if (drmModeSetPlane(drm_data->drm_fd, layer_data->plane_id,
325 output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
326 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
327 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
328 fx, fy, fw, fh) < 0) {
329 TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
330 return TDM_ERROR_OPERATION_FAILED;
333 TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
334 layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
335 layer_data->display_buffer->fb_id,
336 layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
337 layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
338 layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
339 layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
341 return TDM_ERROR_NONE;
345 _tdm_drm_display_cb_event(int fd, unsigned int sequence,
346 unsigned int tv_sec, unsigned int tv_usec,
349 tdm_drm_event_data *event_data = user_data;
350 tdm_drm_output_data *output_data;
353 TDM_ERR("no event data");
357 output_data = event_data->output_data;
359 switch (event_data->type) {
360 case TDM_DRM_EVENT_TYPE_PAGEFLIP:
361 if (output_data->commit_func)
362 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
363 event_data->user_data);
365 case TDM_DRM_EVENT_TYPE_WAIT:
366 if (output_data->vblank_func)
367 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec,
368 event_data->user_data);
370 case TDM_DRM_EVENT_TYPE_COMMIT:
371 if (output_data->commit_func)
372 output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
373 event_data->user_data);
383 _tdm_drm_display_create_layer_list(tdm_drm_data *drm_data)
385 tdm_drm_output_data *output_data = NULL;
388 if (LIST_IS_EMPTY(&drm_data->output_list)) {
389 TDM_ERR("no output");
390 return TDM_ERROR_OPERATION_FAILED;
393 /* The TDM drm backend only support one output. */
394 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) {
398 if (drm_data->plane_res->count_planes == 0) {
399 TDM_ERR("no layer error");
400 return TDM_ERROR_OPERATION_FAILED;
403 for (i = 0; i < drm_data->plane_res->count_planes; i++) {
404 tdm_drm_layer_data *layer_data;
405 drmModePlanePtr plane;
407 plane = drmModeGetPlane(drm_data->drm_fd, drm_data->plane_res->planes[i]);
413 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
414 drmModeFreePlane(plane);
418 layer_data = calloc(1, sizeof(tdm_drm_layer_data));
420 TDM_ERR("alloc failed");
421 drmModeFreePlane(plane);
425 layer_data->drm_data = drm_data;
426 layer_data->output_data = output_data;
427 layer_data->plane_id = drm_data->plane_res->planes[i];
429 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
430 TDM_LAYER_CAPABILITY_GRAPHIC;
431 output_data->primary_layer = layer_data;
433 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) capabilities(%x)",
434 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
435 layer_data->capabilities);
437 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
439 drmModeFreePlane(plane);
441 /* can't take care of other planes for various hardware devices */
445 return TDM_ERROR_NONE;
448 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
451 _tdm_drm_display_get_property(tdm_drm_data *drm_data,
452 unsigned int obj_id, unsigned int obj_type,
453 const char *name, unsigned int *value,
456 drmModeObjectPropertiesPtr props = NULL;
459 props = drmModeObjectGetProperties(drm_data->drm_fd, obj_id, obj_type);
461 return TDM_ERROR_OPERATION_FAILED;
463 for (i = 0; i < props->count_props; i++) {
464 drmModePropertyPtr prop = drmModeGetProperty(drm_data->drm_fd,
470 if (!strcmp(prop->name, name)) {
472 *is_immutable = prop->flags & DRM_MODE_PROP_IMMUTABLE;
474 *value = (unsigned int)props->prop_values[i];
475 drmModeFreeProperty(prop);
476 drmModeFreeObjectProperties(props);
477 return TDM_ERROR_NONE;
480 drmModeFreeProperty(prop);
482 drmModeFreeObjectProperties(props);
483 TDM_DBG("coundn't find '%s' property", name);
484 return TDM_ERROR_OPERATION_FAILED;
488 _tdm_drm_display_create_layer_list_type(tdm_drm_data *drm_data)
490 tdm_drm_output_data *output_data = NULL;
491 drmModePlanePtr *planes = NULL;
492 unsigned int *types = NULL;
493 unsigned int type = 0;
494 int plane_cnt, primary_cnt, ovl_cnt, cursor_cnt;
495 int opos_next, cpos_next;
499 if (LIST_IS_EMPTY(&drm_data->output_list)) {
500 TDM_ERR("no output");
501 return TDM_ERROR_OPERATION_FAILED;
504 /* The TDM drm backend only support one output. */
505 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) {
509 ret = _tdm_drm_display_get_property(drm_data,
510 drm_data->plane_res->planes[0],
511 DRM_MODE_OBJECT_PLANE, "type", &type,
513 if (ret != TDM_ERROR_NONE) {
514 TDM_ERR("plane doesn't have 'type' property. Call a fallback function");
516 /* if a plane doesn't have "type" property, we call a fallback function
519 return _tdm_drm_display_create_layer_list(drm_data);
522 planes = calloc(drm_data->plane_res->count_planes, sizeof(drmModePlanePtr));
524 TDM_ERR("alloc failed");
528 types = calloc(drm_data->plane_res->count_planes, sizeof(unsigned int));
530 TDM_ERR("alloc failed");
535 for (i = 0; i < drm_data->plane_res->count_planes; i++) {
536 drmModePlanePtr plane;
538 plane = drmModeGetPlane(drm_data->drm_fd, drm_data->plane_res->planes[i]);
540 TDM_ERR("no plane(%d)", drm_data->plane_res->planes[i]);
544 if ((plane->possible_crtcs & (1 << output_data->pipe)) == 0) {
545 drmModeFreePlane(plane);
549 ret = _tdm_drm_display_get_property(drm_data,
550 drm_data->plane_res->planes[i],
551 DRM_MODE_OBJECT_PLANE, "type", &type,
553 if (ret != TDM_ERROR_NONE) {
554 drmModeFreePlane(plane);
555 TDM_ERR("plane(%d) doesn't have 'type' info",
556 drm_data->plane_res->planes[i]);
560 planes[plane_cnt] = plane;
561 types[plane_cnt] = type;
565 primary_cnt = ovl_cnt = cursor_cnt = 0;
566 for (i = 0; i < plane_cnt; i++) {
567 if (types[i] == DRM_PLANE_TYPE_CURSOR)
569 else if (types[i] == DRM_PLANE_TYPE_OVERLAY)
571 else if (types[i] == DRM_PLANE_TYPE_PRIMARY)
574 TDM_ERR("invalid type(%d)", types[i]);
577 if (primary_cnt != 1) {
578 TDM_ERR("primary layer count(%d) should be one", primary_cnt);
584 for (i = 0; i < plane_cnt; i++) {
585 tdm_drm_layer_data *layer_data;
587 layer_data = calloc(1, sizeof(tdm_drm_layer_data));
589 TDM_ERR("alloc failed");
593 layer_data->drm_data = drm_data;
594 layer_data->output_data = output_data;
595 layer_data->plane_id = planes[i]->plane_id;
597 if (types[i] == DRM_PLANE_TYPE_CURSOR) {
598 layer_data->capabilities = TDM_LAYER_CAPABILITY_CURSOR |
599 TDM_LAYER_CAPABILITY_GRAPHIC;
600 layer_data->zpos = cpos_next++;
601 } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
602 layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
603 TDM_LAYER_CAPABILITY_GRAPHIC;
604 layer_data->zpos = opos_next++;
605 } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
606 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
607 TDM_LAYER_CAPABILITY_GRAPHIC;
608 layer_data->zpos = 0;
609 output_data->primary_layer = layer_data;
615 TDM_INFO("layer_data(%p) plane_id(%d) crtc_id(%d) zpos(%d) capabilities(%x)",
616 layer_data, layer_data->plane_id, layer_data->output_data->crtc_id,
617 layer_data->zpos, layer_data->capabilities);
619 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
622 for (i = 0; i < plane_cnt; i++)
624 drmModeFreePlane(planes[i]);
629 return TDM_ERROR_NONE;
633 for (i = 0; i < drm_data->plane_res->count_planes; i++)
635 drmModeFreePlane(planes[i]);
641 return TDM_ERROR_OPERATION_FAILED;
646 _tdm_drm_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
648 tdm_drm_data *drm_data;
649 tdm_drm_display_buffer *display_buffer;
653 TDM_ERR("no user_data");
657 TDM_ERR("no buffer");
661 drm_data = (tdm_drm_data *)user_data;
663 display_buffer = _tdm_drm_display_find_buffer(drm_data, buffer);
664 if (!display_buffer) {
665 TDM_ERR("no display_buffer");
668 LIST_DEL(&display_buffer->link);
670 if (display_buffer->fb_id > 0) {
671 ret = drmModeRmFB(drm_data->drm_fd, display_buffer->fb_id);
673 TDM_ERR("rm fb failed");
676 TDM_DBG("drmModeRmFB success!!! fb_id:%d", display_buffer->fb_id);
678 TDM_DBG("drmModeRmFB not called fb_id:%d", display_buffer->fb_id);
680 free(display_buffer);
684 tdm_drm_display_create_layer_list(tdm_drm_data *drm_data)
686 tdm_drm_output_data *output_data = NULL;
689 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
690 if (drm_data->has_universal_plane)
691 ret = _tdm_drm_display_create_layer_list_type(drm_data);
694 ret = _tdm_drm_display_create_layer_list(drm_data);
696 if (ret != TDM_ERROR_NONE)
699 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) {
700 if (!output_data->primary_layer) {
701 TDM_ERR("output(%d) no primary layer", output_data->pipe);
702 return TDM_ERROR_OPERATION_FAILED;
706 return TDM_ERROR_NONE;
710 tdm_drm_display_destroy_output_list(tdm_drm_data *drm_data)
712 tdm_drm_output_data *o = NULL, *oo = NULL;
714 if (LIST_IS_EMPTY(&drm_data->output_list))
717 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &drm_data->output_list, link) {
719 if (!LIST_IS_EMPTY(&o->layer_list)) {
720 tdm_drm_layer_data *l = NULL, *ll = NULL;
721 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
727 free(o->output_modes);
733 tdm_drm_display_update_output_status(tdm_drm_data *drm_data)
735 tdm_drm_output_data *output_data = NULL;
737 if (LIST_IS_EMPTY(&drm_data->output_list))
740 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) {
741 drmModeConnectorPtr connector;
742 tdm_output_conn_status new_status;
744 connector = drmModeGetConnector(drm_data->drm_fd,
745 output_data->connector_id);
747 TDM_ERR("no connector: %d", output_data->connector_id);
751 if (connector->connection == DRM_MODE_CONNECTED)
752 new_status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
754 new_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
756 _tdm_drm_output_update_status(output_data, new_status);
758 drmModeFreeConnector(connector);
763 tdm_drm_display_create_output_list(tdm_drm_data *drm_data)
765 tdm_drm_output_data *output_data;
770 RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&drm_data->output_list),
771 TDM_ERROR_OPERATION_FAILED);
773 for (i = 0; i < drm_data->mode_res->count_connectors; i++) {
774 drmModeConnectorPtr connector;
775 drmModeEncoderPtr encoder;
776 int crtc_id = 0, c, j;
778 connector = drmModeGetConnector(drm_data->drm_fd,
779 drm_data->mode_res->connectors[i]);
781 TDM_ERR("no connector");
782 ret = TDM_ERROR_OPERATION_FAILED;
786 /* The TDM drm backend is not interested with disconnected connectors.
787 * And it only considers 1 connected connector because it is the TDM
788 * reference backend and can't take care of all hardware devices.
789 * To support various connectors, planes and crtcs, the new TDM backend
790 * should be implemented.
792 if (connector->connection != DRM_MODE_CONNECTED) {
793 drmModeFreeConnector(connector);
797 if (connector->count_encoders != 1) {
798 TDM_ERR("too many encoders: %d", connector->count_encoders);
799 drmModeFreeConnector(connector);
800 ret = TDM_ERROR_OPERATION_FAILED;
804 encoder = drmModeGetEncoder(drm_data->drm_fd, connector->encoders[0]);
806 TDM_ERR("no encoder");
807 drmModeFreeConnector(connector);
808 ret = TDM_ERROR_OPERATION_FAILED;
812 for (c = 0; c < drm_data->mode_res->count_crtcs; c++) {
813 if (allocated & (1 << c))
816 if ((encoder->possible_crtcs & (1 << c)) == 0)
819 crtc_id = drm_data->mode_res->crtcs[c];
820 allocated |= (1 << c);
825 TDM_ERR("no possible crtc");
826 drmModeFreeConnector(connector);
827 ret = TDM_ERROR_OPERATION_FAILED;
831 output_data = calloc(1, sizeof(tdm_drm_output_data));
833 TDM_ERR("alloc failed");
834 drmModeFreeConnector(connector);
835 drmModeFreeEncoder(encoder);
836 ret = TDM_ERROR_OUT_OF_MEMORY;
840 LIST_INITHEAD(&output_data->layer_list);
842 output_data->drm_data = drm_data;
843 output_data->connector_id = drm_data->mode_res->connectors[i];
844 output_data->encoder_id = encoder->encoder_id;
845 output_data->crtc_id = crtc_id;
846 output_data->pipe = c;
847 output_data->connector_type = connector->connector_type;
848 output_data->connector_type_id = connector->connector_type_id;
850 if (connector->connection == DRM_MODE_CONNECTED)
851 output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
853 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
855 for (j = 0; j < connector->count_props; j++) {
856 drmModePropertyPtr prop = drmModeGetProperty(drm_data->drm_fd,
857 connector->props[j]);
860 if (!strcmp(prop->name, "DPMS")) {
861 output_data->dpms_prop_id = connector->props[j];
862 drmModeFreeProperty(prop);
865 drmModeFreeProperty(prop);
868 if (output_data->dpms_prop_id == 0)
869 TDM_WRN("not support DPMS");
871 output_data->count_modes = connector->count_modes;
872 output_data->drm_modes = calloc(connector->count_modes,
873 sizeof(drmModeModeInfo));
874 if (!output_data->drm_modes) {
875 TDM_ERR("alloc failed");
877 drmModeFreeConnector(connector);
878 drmModeFreeEncoder(encoder);
879 ret = TDM_ERROR_OUT_OF_MEMORY;
882 output_data->output_modes = calloc(connector->count_modes,
883 sizeof(tdm_output_mode));
884 if (!output_data->output_modes) {
885 TDM_ERR("alloc failed");
886 free(output_data->drm_modes);
888 drmModeFreeConnector(connector);
889 drmModeFreeEncoder(encoder);
890 ret = TDM_ERROR_OUT_OF_MEMORY;
893 for (j = 0; j < connector->count_modes; j++) {
894 output_data->drm_modes[j] = connector->modes[j];
895 _tdm_drm_display_to_tdm_mode(&output_data->drm_modes[j],
896 &output_data->output_modes[j]);
899 LIST_ADDTAIL(&output_data->link, &drm_data->output_list);
901 TDM_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
902 output_data, output_data->connector_id, output_data->status,
903 output_data->connector_type,
904 output_data->connector_type_id, output_data->encoder_id, output_data->crtc_id,
905 output_data->pipe, output_data->dpms_prop_id);
907 drmModeFreeEncoder(encoder);
908 drmModeFreeConnector(connector);
910 /* The TDM drm backend is not interested with disconnected connectors.
911 * And it only considers 1 connected connector because it is the TDM
912 * reference backend and can't take care of all hardware devices.
913 * To support various connectors, planes and crtcs, the new TDM backend
914 * should be implemented.
919 TDM_DBG("output count: %d", drm_data->mode_res->count_connectors);
921 return TDM_ERROR_NONE;
923 tdm_drm_display_destroy_output_list(drm_data);
928 drm_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
930 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
932 caps->max_layer_count = -1; /* not defined */
934 return TDM_ERROR_NONE;
938 drm_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps)
940 return tdm_drm_pp_get_capability(bdata, caps);
944 drm_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
946 tdm_drm_data *drm_data = bdata;
947 tdm_drm_output_data *output_data = NULL;
948 tdm_output **outputs;
952 RETURN_VAL_IF_FAIL(drm_data, NULL);
953 RETURN_VAL_IF_FAIL(count, NULL);
956 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link)
960 ret = TDM_ERROR_NONE;
964 /* will be freed in frontend */
965 outputs = calloc(*count, sizeof(tdm_drm_output_data *));
967 TDM_ERR("failed: alloc memory");
969 ret = TDM_ERROR_OUT_OF_MEMORY;
974 LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link)
975 outputs[i++] = output_data;
978 *error = TDM_ERROR_NONE;
988 drm_display_get_fd(tdm_backend_data *bdata, int *fd)
990 tdm_drm_data *drm_data = bdata;
992 RETURN_VAL_IF_FAIL(drm_data, TDM_ERROR_INVALID_PARAMETER);
993 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
995 *fd = drm_data->drm_fd;
997 return TDM_ERROR_NONE;
1001 drm_display_handle_events(tdm_backend_data *bdata)
1003 tdm_drm_data *drm_data = bdata;
1004 drmEventContext ctx;
1006 RETURN_VAL_IF_FAIL(drm_data, TDM_ERROR_INVALID_PARAMETER);
1008 memset(&ctx, 0, sizeof(drmEventContext));
1010 ctx.version = DRM_EVENT_CONTEXT_VERSION;
1011 ctx.page_flip_handler = _tdm_drm_display_cb_event;
1012 ctx.vblank_handler = _tdm_drm_display_cb_event;
1014 drmHandleEvent(drm_data->drm_fd, &ctx);
1016 return TDM_ERROR_NONE;
1020 drm_display_create_pp(tdm_backend_data *bdata, tdm_error *error)
1022 tdm_drm_data *drm_data = bdata;
1024 RETURN_VAL_IF_FAIL(drm_data, NULL);
1026 return tdm_drm_pp_create(drm_data, error);
1030 drm_output_get_capability(tdm_output *output, tdm_caps_output *caps)
1032 tdm_drm_output_data *output_data = output;
1033 tdm_drm_data *drm_data;
1034 drmModeConnectorPtr connector = NULL;
1035 drmModeCrtcPtr crtc = NULL;
1036 drmModeObjectPropertiesPtr props = NULL;
1040 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1041 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1043 memset(caps, 0, sizeof(tdm_caps_output));
1045 drm_data = output_data->drm_data;
1047 snprintf(caps->maker, TDM_NAME_LEN, "unknown");
1048 snprintf(caps->model, TDM_NAME_LEN, "unknown");
1049 snprintf(caps->name, TDM_NAME_LEN, "unknown");
1051 caps->status = output_data->status;
1052 caps->type = output_data->connector_type;
1053 caps->type_id = output_data->connector_type_id;
1055 connector = drmModeGetConnector(drm_data->drm_fd, output_data->connector_id);
1056 RETURN_VAL_IF_FAIL(connector, TDM_ERROR_OPERATION_FAILED);
1058 caps->mode_count = connector->count_modes;
1059 caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count);
1061 ret = TDM_ERROR_OUT_OF_MEMORY;
1062 TDM_ERR("alloc failed\n");
1065 for (i = 0; i < caps->mode_count; i++)
1066 caps->modes[i] = output_data->output_modes[i];
1068 caps->mmWidth = connector->mmWidth;
1069 caps->mmHeight = connector->mmHeight;
1070 caps->subpixel = connector->subpixel;
1072 caps->min_w = drm_data->mode_res->min_width;
1073 caps->min_h = drm_data->mode_res->min_height;
1074 caps->max_w = drm_data->mode_res->max_width;
1075 caps->max_h = drm_data->mode_res->max_height;
1076 caps->preferred_align = -1;
1078 crtc = drmModeGetCrtc(drm_data->drm_fd, output_data->crtc_id);
1080 ret = TDM_ERROR_OPERATION_FAILED;
1081 TDM_ERR("get crtc failed: %m\n");
1085 props = drmModeObjectGetProperties(drm_data->drm_fd, output_data->crtc_id,
1086 DRM_MODE_OBJECT_CRTC);
1088 ret = TDM_ERROR_OPERATION_FAILED;
1089 TDM_ERR("get crtc properties failed: %m\n");
1093 caps->prop_count = props->count_props;
1094 caps->props = calloc(1, sizeof(tdm_prop) * caps->prop_count);
1096 ret = TDM_ERROR_OUT_OF_MEMORY;
1097 TDM_ERR("alloc failed\n");
1101 for (i = 0; i < caps->prop_count; i++) {
1102 drmModePropertyPtr prop = drmModeGetProperty(drm_data->drm_fd, props->props[i]);
1105 snprintf(caps->props[i].name, TDM_NAME_LEN, "%s", prop->name);
1106 caps->props[i].id = props->props[i];
1107 drmModeFreeProperty(prop);
1110 drmModeFreeObjectProperties(props);
1111 drmModeFreeCrtc(crtc);
1112 drmModeFreeConnector(connector);
1114 return TDM_ERROR_NONE;
1116 drmModeFreeCrtc(crtc);
1117 drmModeFreeObjectProperties(props);
1118 drmModeFreeConnector(connector);
1121 memset(caps, 0, sizeof(tdm_caps_output));
1126 drm_output_get_layers(tdm_output *output, int *count, tdm_error *error)
1128 tdm_drm_output_data *output_data = output;
1129 tdm_drm_layer_data *layer_data = NULL;
1134 RETURN_VAL_IF_FAIL(output_data, NULL);
1135 RETURN_VAL_IF_FAIL(count, NULL);
1138 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1142 ret = TDM_ERROR_NONE;
1146 /* will be freed in frontend */
1147 layers = calloc(*count, sizeof(tdm_drm_layer_data *));
1149 TDM_ERR("failed: alloc memory");
1151 ret = TDM_ERROR_OUT_OF_MEMORY;
1156 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1157 layers[i++] = layer_data;
1160 *error = TDM_ERROR_NONE;
1170 drm_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
1172 tdm_drm_output_data *output_data = output;
1173 tdm_drm_data *drm_data;
1176 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1177 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1179 drm_data = output_data->drm_data;
1180 ret = drmModeObjectSetProperty(drm_data->drm_fd,
1181 output_data->crtc_id, DRM_MODE_OBJECT_CRTC,
1184 TDM_ERR("set property failed: %m");
1185 return TDM_ERROR_OPERATION_FAILED;
1188 return TDM_ERROR_NONE;
1192 drm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
1194 tdm_drm_output_data *output_data = output;
1195 tdm_drm_data *drm_data;
1196 drmModeObjectPropertiesPtr props;
1199 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1200 RETURN_VAL_IF_FAIL(output_data->crtc_id > 0, TDM_ERROR_INVALID_PARAMETER);
1201 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1203 drm_data = output_data->drm_data;
1204 props = drmModeObjectGetProperties(drm_data->drm_fd, output_data->crtc_id,
1205 DRM_MODE_OBJECT_CRTC);
1206 if (props == NULL) {
1207 TDM_ERR("get property failed: %m");
1208 return TDM_ERROR_OPERATION_FAILED;
1211 for (i = 0; i < props->count_props; i++)
1212 if (props->props[i] == id) {
1213 (*value).u32 = (uint)props->prop_values[i];
1217 drmModeFreeObjectProperties(props);
1219 return TDM_ERROR_NONE;
1223 drm_output_wait_vblank(tdm_output *output, int interval, int sync,
1226 tdm_drm_output_data *output_data = output;
1227 tdm_drm_data *drm_data;
1228 tdm_drm_event_data *event_data;
1232 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1234 event_data = calloc(1, sizeof(tdm_drm_event_data));
1236 TDM_ERR("alloc failed");
1237 return TDM_ERROR_OUT_OF_MEMORY;
1240 drm_data = output_data->drm_data;
1242 ret = _tdm_drm_display_get_cur_msc(drm_data->drm_fd, output_data->pipe,
1244 if (ret != TDM_ERROR_NONE)
1247 target_msc += interval;
1249 event_data->type = TDM_DRM_EVENT_TYPE_WAIT;
1250 event_data->output_data = output_data;
1251 event_data->user_data = user_data;
1253 ret = _tdm_drm_display_wait_vblank(drm_data->drm_fd, output_data->pipe,
1254 &target_msc, event_data);
1255 if (ret != TDM_ERROR_NONE)
1258 return TDM_ERROR_NONE;
1265 drm_output_set_vblank_handler(tdm_output *output,
1266 tdm_output_vblank_handler func)
1268 tdm_drm_output_data *output_data = output;
1270 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1271 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1273 output_data->vblank_func = func;
1275 return TDM_ERROR_NONE;
1279 drm_output_commit(tdm_output *output, int sync, void *user_data)
1281 tdm_drm_output_data *output_data = output;
1282 tdm_drm_data *drm_data;
1283 tdm_drm_layer_data *layer_data = NULL;
1285 int do_waitvblank = 1;
1287 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1289 drm_data = output_data->drm_data;
1291 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1292 if (layer_data == output_data->primary_layer) {
1293 ret = _tdm_drm_display_commit_primary_layer(layer_data, user_data,
1295 if (ret != TDM_ERROR_NONE)
1298 ret = _tdm_drm_display_commit_layer(layer_data);
1299 if (ret != TDM_ERROR_NONE)
1304 if (do_waitvblank == 1) {
1305 tdm_drm_event_data *event_data = calloc(1, sizeof(tdm_drm_event_data));
1309 TDM_ERR("alloc failed");
1310 return TDM_ERROR_OUT_OF_MEMORY;
1313 ret = _tdm_drm_display_get_cur_msc(drm_data->drm_fd, output_data->pipe,
1315 if (ret != TDM_ERROR_NONE) {
1322 event_data->type = TDM_DRM_EVENT_TYPE_COMMIT;
1323 event_data->output_data = output_data;
1324 event_data->user_data = user_data;
1326 ret = _tdm_drm_display_wait_vblank(drm_data->drm_fd, output_data->pipe,
1327 &target_msc, event_data);
1328 if (ret != TDM_ERROR_NONE) {
1334 return TDM_ERROR_NONE;
1338 drm_output_set_commit_handler(tdm_output *output,
1339 tdm_output_commit_handler func)
1341 tdm_drm_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->commit_func = func;
1348 return TDM_ERROR_NONE;
1352 drm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1354 tdm_drm_output_data *output_data = output;
1355 tdm_drm_data *drm_data;
1358 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1360 if (output_data->dpms_prop_id == 0) {
1361 TDM_WRN("not support DPMS");
1362 return TDM_ERROR_OPERATION_FAILED;
1365 drm_data = output_data->drm_data;
1366 ret = drmModeObjectSetProperty(drm_data->drm_fd,
1367 output_data->connector_id, DRM_MODE_OBJECT_CONNECTOR,
1368 output_data->dpms_prop_id, dpms_value);
1370 TDM_ERR("set dpms failed: %m");
1371 return TDM_ERROR_OPERATION_FAILED;
1374 return TDM_ERROR_NONE;
1378 drm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1380 tdm_drm_output_data *output_data = output;
1381 tdm_drm_data *drm_data;
1382 drmModeObjectPropertiesPtr props;
1385 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1386 RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
1388 drm_data = output_data->drm_data;
1389 props = drmModeObjectGetProperties(drm_data->drm_fd, output_data->connector_id,
1390 DRM_MODE_OBJECT_CONNECTOR);
1391 if (props == NULL) {
1392 TDM_ERR("get property failed: %m");
1393 return TDM_ERROR_OPERATION_FAILED;
1396 for (i = 0; i < props->count_props; i++)
1397 if (props->props[i] == output_data->dpms_prop_id) {
1398 *dpms_value = (uint)props->prop_values[i];
1402 drmModeFreeObjectProperties(props);
1404 return TDM_ERROR_NONE;
1408 drm_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1410 tdm_drm_output_data *output_data = output;
1412 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1413 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1415 output_data->current_mode = mode;
1416 output_data->mode_changed = 1;
1418 return TDM_ERROR_NONE;
1422 drm_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1424 tdm_drm_output_data *output_data = output;
1426 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1427 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1429 *mode = output_data->current_mode;
1431 return TDM_ERROR_NONE;
1435 drm_output_set_status_handler(tdm_output *output,
1436 tdm_output_status_handler func,
1439 tdm_drm_output_data *output_data = output;
1441 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1442 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1444 output_data->status_func = func;
1445 output_data->status_user_data = user_data;
1447 return TDM_ERROR_NONE;
1451 drm_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
1453 tdm_drm_layer_data *layer_data = layer;
1454 tdm_drm_data *drm_data;
1455 drmModePlanePtr plane = NULL;
1456 drmModeObjectPropertiesPtr props = NULL;
1457 int i, format_count = 0;
1460 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1461 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1463 memset(caps, 0, sizeof(tdm_caps_layer));
1465 drm_data = layer_data->drm_data;
1466 plane = drmModeGetPlane(drm_data->drm_fd, layer_data->plane_id);
1468 TDM_ERR("get plane failed: %m");
1469 ret = TDM_ERROR_OPERATION_FAILED;
1473 caps->capabilities = layer_data->capabilities;
1474 caps->zpos = layer_data->zpos; /* if VIDEO layer, zpos is -1 */
1476 caps->format_count = plane->count_formats;
1477 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1478 if (!caps->formats) {
1479 ret = TDM_ERROR_OUT_OF_MEMORY;
1480 TDM_ERR("alloc failed\n");
1484 for (i = 0; i < caps->format_count; i++) {
1485 /* TODO: kernel reports wrong formats */
1486 if (plane->formats[i] != DRM_FORMAT_XRGB8888 &&
1487 plane->formats[i] != DRM_FORMAT_ARGB8888)
1489 caps->formats[i] = tdm_drm_format_to_tbm_format(plane->formats[i]);
1493 caps->format_count = format_count;
1495 props = drmModeObjectGetProperties(drm_data->drm_fd, layer_data->plane_id,
1496 DRM_MODE_OBJECT_PLANE);
1498 ret = TDM_ERROR_OPERATION_FAILED;
1499 TDM_ERR("get plane properties failed: %m\n");
1503 caps->props = calloc(1, sizeof(tdm_prop) * props->count_props);
1505 ret = TDM_ERROR_OUT_OF_MEMORY;
1506 TDM_ERR("alloc failed\n");
1510 caps->prop_count = 0;
1511 for (i = 0; i < props->count_props; i++) {
1512 drmModePropertyPtr prop = drmModeGetProperty(drm_data->drm_fd, props->props[i]);
1515 if (!strncmp(prop->name, "type", TDM_NAME_LEN))
1517 if (!strncmp(prop->name, "zpos", TDM_NAME_LEN))
1519 snprintf(caps->props[i].name, TDM_NAME_LEN, "%s", prop->name);
1520 caps->props[i].id = props->props[i];
1522 drmModeFreeProperty(prop);
1525 drmModeFreeObjectProperties(props);
1526 drmModeFreePlane(plane);
1528 return TDM_ERROR_NONE;
1530 drmModeFreeObjectProperties(props);
1531 drmModeFreePlane(plane);
1532 free(caps->formats);
1534 memset(caps, 0, sizeof(tdm_caps_layer));
1539 drm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1541 tdm_drm_layer_data *layer_data = layer;
1542 tdm_drm_data *drm_data;
1545 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1546 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
1548 drm_data = layer_data->drm_data;
1549 ret = drmModeObjectSetProperty(drm_data->drm_fd,
1550 layer_data->plane_id, DRM_MODE_OBJECT_PLANE,
1553 TDM_ERR("set property failed: %m");
1554 return TDM_ERROR_OPERATION_FAILED;
1557 return TDM_ERROR_NONE;
1561 drm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1563 tdm_drm_layer_data *layer_data = layer;
1564 tdm_drm_data *drm_data;
1565 drmModeObjectPropertiesPtr props;
1568 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1569 RETURN_VAL_IF_FAIL(layer_data->plane_id > 0, TDM_ERROR_INVALID_PARAMETER);
1570 RETURN_VAL_IF_FAIL(value, TDM_ERROR_INVALID_PARAMETER);
1572 drm_data = layer_data->drm_data;
1573 props = drmModeObjectGetProperties(drm_data->drm_fd, layer_data->plane_id,
1574 DRM_MODE_OBJECT_PLANE);
1575 if (props == NULL) {
1576 TDM_ERR("get property failed: %m");
1577 return TDM_ERROR_OPERATION_FAILED;
1580 for (i = 0; i < props->count_props; i++)
1581 if (props->props[i] == id) {
1582 (*value).u32 = (uint)props->prop_values[i];
1586 drmModeFreeObjectProperties(props);
1588 return TDM_ERROR_NONE;
1592 drm_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1594 tdm_drm_layer_data *layer_data = layer;
1596 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1597 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1599 layer_data->info = *info;
1600 layer_data->info_changed = 1;
1602 return TDM_ERROR_NONE;
1606 drm_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1608 tdm_drm_layer_data *layer_data = layer;
1610 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1611 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1613 *info = layer_data->info;
1615 return TDM_ERROR_NONE;
1619 drm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
1621 tdm_drm_layer_data *layer_data = layer;
1622 tdm_drm_data *drm_data;
1623 tdm_drm_display_buffer *display_buffer;
1624 tdm_error err = TDM_ERROR_NONE;
1627 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1628 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
1630 drm_data = layer_data->drm_data;
1632 display_buffer = _tdm_drm_display_find_buffer(drm_data, buffer);
1633 if (!display_buffer) {
1634 display_buffer = calloc(1, sizeof(tdm_drm_display_buffer));
1635 if (!display_buffer) {
1636 TDM_ERR("alloc failed");
1637 return TDM_ERROR_OUT_OF_MEMORY;
1639 display_buffer->buffer = buffer;
1641 err = tdm_buffer_add_destroy_handler(buffer, _tdm_drm_display_cb_destroy_buffer,
1643 if (err != TDM_ERROR_NONE) {
1644 TDM_ERR("add destroy handler fail");
1645 free(display_buffer);
1646 return TDM_ERROR_OPERATION_FAILED;
1649 LIST_ADDTAIL(&display_buffer->link, &drm_data->buffer_list);
1652 if (display_buffer->fb_id == 0) {
1654 unsigned int height;
1655 unsigned int format;
1656 unsigned int handles[4] = {0,};
1657 unsigned int pitches[4] = {0,};
1658 unsigned int offsets[4] = {0,};
1661 width = tbm_surface_get_width(buffer);
1662 height = tbm_surface_get_height(buffer);
1663 format = tbm_surface_get_format(buffer);
1664 count = tbm_surface_internal_get_num_bos(buffer);
1665 for (i = 0; i < count; i++) {
1666 tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
1667 handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
1669 count = tbm_surface_internal_get_num_planes(format);
1670 for (i = 0; i < count; i++)
1671 tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
1673 ret = drmModeAddFB2(drm_data->drm_fd, width, height, format,
1674 handles, pitches, offsets, &display_buffer->fb_id, 0);
1676 TDM_ERR("add fb failed: %m");
1677 return TDM_ERROR_OPERATION_FAILED;
1679 TDM_DBG("drm_data->drm_fd : %d, display_buffer->fb_id:%u", drm_data->drm_fd,
1680 display_buffer->fb_id);
1683 display_buffer->width = pitches[0] >> 2;
1685 display_buffer->width = pitches[0];
1688 layer_data->display_buffer = display_buffer;
1689 layer_data->display_buffer_changed = 1;
1691 return TDM_ERROR_NONE;
1695 drm_layer_unset_buffer(tdm_layer *layer)
1697 tdm_drm_layer_data *layer_data = layer;
1699 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1701 layer_data->display_buffer = NULL;
1702 layer_data->display_buffer_changed = 1;
1704 return TDM_ERROR_NONE;