5 #include <tdm_helper.h>
8 #include <video/sprdfb.h>
9 #include <tbm_surface.h>
10 #include <tbm_surface_queue.h>
15 /** @TODO fb event struct */
17 typedef struct drm_event hw_event_t;
20 #define FB_DEV_LCD "/dev/fb0"
22 #define HW_LAYER_NUM 2
24 #define LIST_INSERT_AFTER(__after, __item) \
25 (__item)->prev = (__after); \
26 (__item)->next = (__after)->next; \
27 (__after)->next->prev = (__item); \
28 (__after)->next = (__item);
30 typedef struct _tdm_sprd_output_data tdm_sprd_output_data;
31 typedef struct _tdm_sprd_layer_data tdm_sprd_layer_data;
32 typedef struct _tdm_sprd_hwc_data tdm_sprd_hwc_data;
33 typedef struct _tdm_sprd_hwc_window_data tdm_sprd_hwc_window_data;
34 typedef struct _tdm_sprd_vblank_data_s tdm_sprd_vblank_data;
41 struct _tdm_sprd_vblank_data_s {
43 tdm_sprd_output_data *output_data;
47 typedef struct _tdm_sprd_display_buffer {
48 struct list_head link;
55 unsigned int handles[4];
57 unsigned int pitches[4];
58 unsigned int offsets[4];
61 } tdm_sprd_display_buffer;
63 typedef struct _tdm_sprd_output_capture_data {
64 tdm_capture * tdm_capture_p;
65 struct list_head link;
66 } tdm_sprd_output_capture_data;
68 struct _tdm_sprd_output_data {
69 struct list_head link;
71 /* data which are fixed at initializing */
72 tdm_sprd_data *sprd_data;
75 tdm_output_mode *output_modes;
76 tdm_output_type connector_type;
77 unsigned int connector_type_id;
78 struct list_head layer_list;
80 tdm_output_vblank_handler vblank_func;
81 tdm_output_commit_handler commit_func;
82 tdm_output_conn_status status;
85 const tdm_output_mode *current_mode;
87 int waiting_vblank_event;
92 struct fb_var_screeninfo mi;
94 tdm_output_dpms dpms_value;
96 struct list_head capture_list;
99 tdm_sprd_hwc_data *hwc_data;
102 struct _tdm_sprd_layer_data {
103 struct list_head link;
105 /* data which are fixed at initializing */
106 tdm_sprd_data *sprd_data;
107 tdm_sprd_output_data *output_data;
108 tdm_layer_capability capabilities;
111 //list of sprd formats
115 /* not fixed data below */
119 tdm_sprd_display_buffer *display_buffer;
120 int display_buffer_changed;
121 /* current hw overlay setting */
128 struct _tdm_sprd_hwc_data {
129 tdm_sprd_hwc_window_data *target_hwc_window;
132 int need_target_window;
135 int target_window_zpos;
137 tdm_sprd_output_data *output_data;
138 struct list_head hwc_window_list;
140 tdm_hwc_commit_handler commit_func;
143 struct _tdm_sprd_hwc_window_data {
144 struct list_head link;
146 /* data which are fixed at initializing */
147 tdm_sprd_hwc_data *hwc_data;
149 /* not fixed data below */
150 tdm_hwc_window_info info;
153 tdm_sprd_display_buffer *display_buffer;
154 int display_buffer_changed;
157 /* client_type stores the initial type given to us by client(compositor) */
158 tdm_hwc_window_composition client_type;
159 /* validated_type stores the type after running Validate */
160 tdm_hwc_window_composition validated_type;
162 tdm_hwc_window_flag flags;
165 typedef struct _Drm_Event_Context {
166 void (*vblank_handler)(int fd, unsigned int sequence, unsigned int tv_sec,
167 unsigned int tv_usec, void *user_data);
168 void (*pp_handler)(int fd, unsigned int prop_id, unsigned int *buf_idx,
169 unsigned int tv_sec, unsigned int tv_usec, void *user_data);
172 tbm_format img_layer_formats[] = {
177 tbm_format osd_layer_formats[] = {
183 tbm_format hwc_window_video_formats[] = {
192 _comp_to_str(tdm_hwc_window_composition composition_type)
194 if (composition_type == TDM_COMPOSITION_CLIENT)
196 else if (composition_type == TDM_COMPOSITION_DEVICE)
198 else if (composition_type == TDM_COMPOSITION_CURSOR)
200 else if (composition_type == TDM_COMPOSITION_NONE)
206 static tbm_surface_queue_h
207 _sprd_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
209 tdm_sprd_hwc_window_data *hwc_window_data = NULL;
210 tbm_surface_queue_h tqueue = NULL;
213 *error = TDM_ERROR_INVALID_PARAMETER;
215 RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
216 hwc_window_data = hwc_window;
218 int wight = hwc_window_data->info.src_config.size.h;
219 int hight = hwc_window_data->info.src_config.size.v;
220 tbm_format format = hwc_window_data->info.src_config.format;
222 tqueue = tbm_surface_queue_create(3, wight, hight, format, TBM_BO_SCANOUT);
224 *error = TDM_ERROR_OPERATION_FAILED;
225 RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
228 *error = TDM_ERROR_NONE;
235 check_hw_restriction(unsigned int output_w, unsigned int buf_w,
236 unsigned int src_x, unsigned int src_w, unsigned int dst_x, unsigned int dst_w,
237 unsigned int *new_src_x, unsigned int *new_src_w,
238 unsigned int *new_dst_x, unsigned int *new_dst_w)
240 int start, end, diff;
248 if (buf_w < MIN_WIDTH || buf_w % 2) {
249 TDM_ERR("buf_w(%d) not 2's multiple or less than %d", buf_w, MIN_WIDTH);
250 return TDM_ERROR_BAD_REQUEST;
253 if (src_x > dst_x || ((dst_x - src_x) + buf_w) > output_w)
258 start = (dst_x < 0) ? 0 : dst_x;
259 end = ((dst_x + dst_w) > output_w) ? output_w : (dst_x + dst_w);
261 /* check window minimun width */
262 if ((end - start) < MIN_WIDTH) {
263 TDM_ERR("visible_w(%d) less than %d", end - start, MIN_WIDTH);
264 return TDM_ERROR_BAD_REQUEST;
267 if (!virtual_screen) {
268 /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */
269 if ((end - start) % 2)
272 /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */
278 *new_dst_w = end - start;
279 *new_src_w = *new_dst_w;
280 diff = start - dst_x;
283 RETURN_VAL_IF_FAIL(*new_src_w > 0, TDM_ERROR_BAD_REQUEST);
284 RETURN_VAL_IF_FAIL(*new_dst_w > 0, TDM_ERROR_BAD_REQUEST);
286 if (src_x != *new_src_x || src_w != *new_src_w || dst_x != *new_dst_x ||
288 TDM_DBG("=> buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)",
289 buf_w, *new_src_x, *new_src_w, *new_dst_x, *new_dst_w, virtual_screen, start,
292 return TDM_ERROR_NONE;
297 static tdm_sprd_display_buffer *
298 _tdm_sprd_display_find_buffer(tdm_sprd_data *sprd_data, tbm_surface_h buffer)
300 tdm_sprd_display_buffer *display_buffer = NULL;
302 LIST_FOR_EACH_ENTRY(display_buffer, &sprd_data->buffer_list, link) {
303 if (display_buffer->buffer == buffer)
304 return display_buffer;
310 static inline uint32_t
311 _get_refresh(struct fb_var_screeninfo *timing)
313 uint32_t pixclock, hfreq, htotal, vtotal;
315 pixclock = PICOS2KHZ(timing->pixclock) * 1000;
317 htotal = timing->xres + timing->right_margin + timing->hsync_len + timing->left_margin;
318 vtotal = timing->yres + timing->lower_margin + timing->vsync_len + timing->upper_margin;
320 if (timing->vmode & FB_VMODE_INTERLACED)
322 if (timing->vmode & FB_VMODE_DOUBLE)
325 hfreq = pixclock / htotal;
326 return hfreq / vtotal;
330 * Convert fb_var_screeninfo to tdm_output_mode
333 _tdm_sprd_display_to_tdm_mode(struct fb_var_screeninfo *timing, tdm_output_mode *mode)
336 if (!timing->pixclock)
339 mode->clock = timing->pixclock / 1000;
340 mode->vrefresh = _get_refresh(timing);
341 mode->hdisplay = timing->xres;
342 mode->hsync_start = mode->hdisplay + timing->right_margin;
343 mode->hsync_end = mode->hsync_start + timing->hsync_len;
344 mode->htotal = mode->hsync_end + timing->left_margin;
346 mode->vdisplay = timing->yres;
347 mode->vsync_start = mode->vdisplay + timing->lower_margin;
348 mode->vsync_end = mode->vsync_start + timing->vsync_len;
349 mode->vtotal = mode->vsync_end + timing->upper_margin;
351 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
353 if (timing->vmode & FB_VMODE_INTERLACED)
354 mode->flags |= DRM_MODE_FLAG_INTERLACE;
356 if (timing->vmode & FB_VMODE_DOUBLE)
357 mode->flags |= DRM_MODE_FLAG_DBLSCAN;
359 int interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
360 snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s", mode->hdisplay, mode->vdisplay, interlaced ? "i" : "");
364 _localdrmWaitVBlank(int fd, drmVBlank *vbl)
366 struct timespec timeout = {0, }, cur = {0, };
369 ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
371 TDM_ERR("clock_gettime failed: %s", strerror(errno));
377 ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
378 vbl->request.type &= ~DRM_VBLANK_RELATIVE;
379 if (ret && errno == EINTR) {
380 clock_gettime(CLOCK_MONOTONIC, &cur);
381 /* Timeout after 1s */
382 if (cur.tv_sec > timeout.tv_sec + 1 || (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >= timeout.tv_nsec)) {
388 } while (ret && errno == EINTR);
396 _tdm_sprd_display_get_cur_msc(int fd, int pipe, uint *msc)
400 vbl.request.type = DRM_VBLANK_RELATIVE;
402 vbl.request.type |= DRM_VBLANK_SECONDARY;
404 vbl.request.sequence = 0;
405 if (_localdrmWaitVBlank(fd, &vbl)) {
406 TDM_ERR("get vblank counter failed: %m");
408 return TDM_ERROR_OPERATION_FAILED;
411 *msc = vbl.reply.sequence;
413 return TDM_ERROR_NONE;
417 _tdm_sprd_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
421 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
423 vbl.request.type |= DRM_VBLANK_SECONDARY;
425 vbl.request.sequence = *target_msc;
426 vbl.request.signal = (unsigned long) (uintptr_t) data;
428 if (_localdrmWaitVBlank(fd, &vbl)) {
430 TDM_ERR("wait vblank failed: %m");
431 return TDM_ERROR_OPERATION_FAILED;
434 *target_msc = vbl.reply.sequence;
436 return TDM_ERROR_NONE;
440 _tdm_sprd_display_output_disable(tdm_sprd_output_data *output_data)
442 tdm_sprd_layer_data *layer_data = NULL;
443 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
444 memset(&layer_data->ovi, 0, sizeof(overlay_info));
446 TDM_DBG("FB_BLANK_POWERDOWN\n");
447 if (ioctl(output_data->fb_fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
448 TDM_ERR("FB_BLANK_POWERDOWN is failed: %s\n", strerror(errno));
449 return TDM_ERROR_OPERATION_FAILED;
451 return TDM_ERROR_NONE;
455 _tdm_sprd_display_output_enable(tdm_sprd_output_data *output_data)
457 TDM_DBG("FB_BLANK_UNBLANK\n");
458 tdm_sprd_layer_data *layer_data = NULL;
459 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
460 memset(&layer_data->ovi, 0, sizeof(overlay_info));
462 if (ioctl(output_data->fb_fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
463 TDM_ERR("FB_BLANK_UNBLANK is failed: %s\n", strerror(errno));
464 return TDM_ERROR_OPERATION_FAILED;
466 return TDM_ERROR_NONE;
470 _tdm_sprd_display_layer_disable(tdm_layer *layer)
472 tdm_sprd_layer_data *layer_data = layer;
474 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
475 if (layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY) {
476 layer_index = SPRD_LAYER_OSD;
477 } else if (layer_data->capabilities & TDM_LAYER_CAPABILITY_OVERLAY) {
478 layer_index = SPRD_LAYER_IMG;
480 TDM_ERR("layer capability (0x%x) not supported\n", layer_data->capabilities);
481 return TDM_ERROR_OPERATION_FAILED;
483 if (layer_data->enabled_flag) {
484 TDM_DBG("SPRD_FB_UNSET_OVERLAY(%d)\n", layer_index);
485 if (ioctl(layer_data->output_data->fb_fd, SPRD_FB_UNSET_OVERLAY, &layer_index) == -1)
486 TDM_ERR("SPRD_FB_UNSET_OVERLAY(%d) error:%s\n", layer_index, strerror(errno));
488 memset(&layer_data->ovi, 0, sizeof(overlay_info));
489 layer_data->enabled_flag = 0;
491 return TDM_ERROR_NONE;
495 _tdm_sprd_tbmformat_to_sprdformat(int tbm_format, overlay_info *ovi)
503 switch (tbm_format) {
504 case TBM_FORMAT_RGB565:
505 ovi->data_type = SPRD_DATA_FORMAT_RGB565;
506 ovi->endian.y = SPRD_DATA_ENDIAN_B0B1B2B3;
507 ovi->endian.u = SPRD_DATA_ENDIAN_B0B1B2B3;
509 case TBM_FORMAT_ARGB8888:
510 case TBM_FORMAT_XRGB8888:
511 ovi->data_type = SPRD_DATA_FORMAT_RGB888;
512 ovi->endian.y = SPRD_DATA_ENDIAN_B0B1B2B3;
513 ovi->endian.u = SPRD_DATA_ENDIAN_B0B1B2B3;
515 case TBM_FORMAT_NV12:
516 ovi->data_type = SPRD_DATA_FORMAT_YUV420;
517 ovi->endian.y = SPRD_DATA_ENDIAN_B3B2B1B0;
518 ovi->endian.u = SPRD_DATA_ENDIAN_B3B2B1B0;
520 case TBM_FORMAT_YUV420:
521 ovi->data_type = SPRD_DATA_FORMAT_YUV420_3P;
522 ovi->endian.y = SPRD_DATA_ENDIAN_B3B2B1B0;
523 ovi->endian.u = SPRD_DATA_ENDIAN_B3B2B1B0;
524 ovi->endian.v = SPRD_DATA_ENDIAN_B3B2B1B0;
527 return TDM_ERROR_INVALID_PARAMETER;
529 return TDM_ERROR_NONE;
533 _tdm_sprd_display_do_commit(tdm_sprd_output_data *output_data)
535 tdm_error res = TDM_ERROR_NONE;
536 tdm_sprd_layer_data *layer_data = NULL;
537 overlay_info ovi = {0};
538 overlay_display ov_disp = {0};
541 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_OPERATION_FAILED);
543 if (output_data->dpms_value != TDM_OUTPUT_DPMS_ON) {
544 output_data->dpms_value = TDM_OUTPUT_DPMS_ON;
545 _tdm_sprd_display_output_enable(output_data);
548 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
550 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
552 if (layer_data->display_buffer) {
553 if (layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY) {
554 layer_index = SPRD_LAYER_OSD;
555 } else if (layer_data->capabilities & TDM_LAYER_CAPABILITY_OVERLAY) {
556 layer_index = SPRD_LAYER_IMG;
558 TDM_ERR("layer capability (0x%x) not supported\n", layer_data->capabilities);
561 tbm_format frmt = layer_data->display_buffer->format;
562 if (_tdm_sprd_tbmformat_to_sprdformat(frmt, &ovi) != TDM_ERROR_NONE) {
563 ovi.data_type = SPRD_DATA_FORMAT_RGB888;
564 ovi.endian.y = SPRD_DATA_ENDIAN_B0B1B2B3;
565 ovi.endian.u = SPRD_DATA_ENDIAN_B0B1B2B3;
566 ovi.endian.v = SPRD_DATA_ENDIAN_B0B1B2B3;
567 TDM_ERR("Unsupported format: %x %c%c%c%c\n", frmt, FOURCC_STR(frmt));
571 ovi.layer_index = layer_index;
572 ovi.size.hsize = layer_data->display_buffer->width;
573 ovi.size.vsize = layer_data->display_buffer->height;
575 ovi.rect.x = layer_data->info.dst_pos.x;
576 ovi.rect.y = layer_data->info.dst_pos.y;
579 int output_width = output_data->mi.xres;
580 int width = layer_data->info.src_config.pos.w;
581 int x = layer_data->info.dst_pos.x;
583 ovi.rect.w = (width + x) <= output_width ? width : output_width - x;
584 ovi.rect.h = layer_data->info.src_config.pos.h;
586 if (ovi.layer_index == SPRD_LAYER_OSD)
587 ov_disp.osd_handle = layer_data->display_buffer->name[0];
588 else if (ovi.layer_index == SPRD_LAYER_IMG)
589 ov_disp.img_handle = layer_data->display_buffer->name[0];
591 if (memcmp(&layer_data->ovi, &ovi, sizeof(overlay_info)) != 0) {
592 TDM_DBG("SPRD_FB_SET_OVERLAY(%d) rect:%dx%d+%d+%d size:%dx%d\n", ovi.layer_index, ovi.rect.w,
593 ovi.rect.h, ovi.rect.x, ovi.rect.y, ovi.size.hsize, ovi.size.vsize);
594 if (ioctl(layer_data->output_data->fb_fd, SPRD_FB_SET_OVERLAY, &ovi) == -1) {
595 TDM_ERR("SPRD_FB_SET_OVERLAY(%d) error:%s\n", layer_index, strerror(errno));
598 memcpy(&layer_data->ovi, &ovi, sizeof(overlay_info));
600 layer_data->enabled_flag = 1;
601 ov_disp.layer_index |= layer_index;
603 tdm_sprd_data *sprd_data = output_data->sprd_data;
605 if (sprd_data->hwc_mode)
606 layer_data->need_unset = 1;
608 _tdm_sprd_display_layer_disable(layer_data);
611 layer_data->display_buffer_changed = layer_data->info_changed = 0;
614 if (ov_disp.layer_index) {
615 ov_disp.display_mode = SPRD_DISPLAY_OVERLAY_SYNC;
617 TDM_DBG("SPRD_FB_DISPLAY_OVERLAY(%d) osd_handle:%d img_handle:%d\n", ov_disp.layer_index, ov_disp.osd_handle,
619 if (ioctl(output_data->fb_fd, SPRD_FB_DISPLAY_OVERLAY, &ov_disp) == -1) {
620 TDM_ERR("SPRD_FB_DISPLAY_OVERLAY(%d) error: %s \n", strerror(errno), ov_disp.layer_index);
621 res = TDM_ERROR_OPERATION_FAILED;
624 // enable_layers |= ov_disp.layer_index;
633 _tdm_sprd_display_cb_pp(int fd, unsigned int prop_id, unsigned int *buf_idx,
634 unsigned int tv_sec, unsigned int tv_usec,
637 tdm_sprd_pp_handler(prop_id, buf_idx, tv_sec, tv_usec, user_data);
643 _tdm_sprd_display_events_handle(int fd, Drm_Event_Context *evctx)
645 #define MAX_BUF_SIZE 1024
647 char buffer[MAX_BUF_SIZE];
651 /* The DRM read semantics guarantees that we always get only
652 * complete events. */
653 len = read(fd, buffer, sizeof buffer);
655 TDM_WRN("warning: the size of the drm_event is 0.");
658 if (len < sizeof * e) {
659 TDM_WRN("warning: the size of the drm_event is less than drm_event structure.");
663 if (len > MAX_BUF_SIZE - sizeof(struct drm_sprd_ipp_event)) {
664 TDM_WRN("warning: the size of the drm_event can be over the maximum size.");
670 e = (struct drm_event *) &buffer[i];
672 case DRM_EVENT_VBLANK: {
673 struct drm_event_vblank *vblank;
675 if (evctx->vblank_handler == NULL)
678 vblank = (struct drm_event_vblank *)e;
679 TDM_DBG("******* VBLANK *******");
680 evctx->vblank_handler (fd, vblank->sequence,
681 vblank->tv_sec, vblank->tv_usec,
682 (void *)((unsigned long)vblank->user_data));
683 TDM_DBG("******* VBLANK *******...");
687 case DRM_EXYNOS_IPP_EVENT: {
688 struct drm_sprd_ipp_event *ipp;
690 if (evctx->pp_handler == NULL)
693 ipp = (struct drm_sprd_ipp_event *)e;
694 TDM_DBG("******* PP *******");
695 evctx->pp_handler (fd, ipp->prop_id, ipp->buf_id,
696 ipp->tv_sec, ipp->tv_usec,
697 (void *)((unsigned long)ipp->user_data));
698 TDM_DBG("******* PP *******...");
702 case DRM_EVENT_FLIP_COMPLETE:
703 /* do nothing for flip complete */
716 _tdm_sprd_display_create_layer_list_LCD(tdm_sprd_output_data *output_data)
718 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
720 tdm_sprd_data *sprd_data = output_data->sprd_data;
721 tdm_sprd_layer_data *layer_data_osd, *layer_data_img;
723 layer_data_osd = calloc(1, sizeof(tdm_sprd_layer_data));
724 if (!layer_data_osd) {
725 TDM_ERR("alloc failed osd");
726 return TDM_ERROR_OUT_OF_MEMORY;
728 layer_data_img = calloc(1, sizeof(tdm_sprd_layer_data));
729 if (!layer_data_img) {
730 TDM_ERR("alloc failed img");
731 free(layer_data_osd);
732 return TDM_ERROR_OUT_OF_MEMORY;
735 /* create OSD layer */
736 layer_data_osd->sprd_data = sprd_data;
737 layer_data_osd->output_data = output_data;
739 layer_data_osd->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
740 TDM_LAYER_CAPABILITY_GRAPHIC |
741 TDM_LAYER_CAPABILITY_SCANOUT |
742 TDM_LAYER_CAPABILITY_RESEVED_MEMORY |
743 TDM_LAYER_CAPABILITY_NO_CROP;
744 layer_data_osd->zpos = 1;
746 layer_data_osd->format_count = sizeof(osd_layer_formats) / sizeof(int);
747 layer_data_osd->formats = osd_layer_formats;
749 TDM_DBG("layer_data_osd(%p) capabilities(0x%x)", layer_data_osd, layer_data_osd->capabilities);
751 LIST_ADDTAIL(&layer_data_osd->link, &output_data->layer_list);
753 /* create IMG layer */
754 layer_data_img->sprd_data = sprd_data;
755 layer_data_img->output_data = output_data;
756 layer_data_img->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
757 TDM_LAYER_CAPABILITY_GRAPHIC |
758 TDM_LAYER_CAPABILITY_SCANOUT |
759 TDM_LAYER_CAPABILITY_RESEVED_MEMORY |
760 TDM_LAYER_CAPABILITY_NO_CROP;
761 layer_data_img->zpos = 0;
763 layer_data_img->format_count = sizeof(img_layer_formats) / sizeof(int);
764 layer_data_img->formats = img_layer_formats;
766 TDM_DBG("layer_data_img(%p) capabilities(0x%x)", layer_data_img, layer_data_img->capabilities);
768 LIST_ADDTAIL(&layer_data_img->link, &output_data->layer_list);
770 return TDM_ERROR_NONE;
774 _tdm_sprd_display_output_update(tdm_sprd_output_data *output)
776 RETURN_VAL_IF_FAIL(output, TDM_ERROR_INVALID_PARAMETER);
777 RETURN_VAL_IF_FAIL(output->fb_fd_name, TDM_ERROR_INVALID_PARAMETER);
780 output->fb_fd = open(output->fb_fd_name, O_RDWR, 0);
782 if (output->fb_fd < 0)
785 if (ioctl(output->fb_fd, FBIOGET_VSCREENINFO, &output->mi) == -1)
788 output->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
790 if (output->mi.activate & FB_ACTIVATE_VBL)
791 output->dpms_value = TDM_OUTPUT_DPMS_ON;
793 output->dpms_value = TDM_OUTPUT_DPMS_OFF;
795 return TDM_ERROR_NONE;
799 if (output->fb_fd > 0) {
800 close(output->fb_fd);
803 output->dpms_value = TDM_OUTPUT_DPMS_OFF;
804 output->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
805 return TDM_ERROR_OPERATION_FAILED;
809 _tdm_sprd_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
811 tdm_sprd_data *sprd_data;
812 tdm_sprd_display_buffer *display_buffer;
813 tdm_sprd_layer_data *layer_data = NULL;
814 tdm_sprd_output_data *output_data = NULL;
816 TDM_ERR("no user_data");
820 TDM_ERR("no buffer");
824 sprd_data = (tdm_sprd_data *) user_data;
826 display_buffer = _tdm_sprd_display_find_buffer(sprd_data, buffer);
827 if (!display_buffer) {
828 TDM_ERR("no display_buffer");
831 TDM_DBG("destroy buffer handle:%d", display_buffer->name[0]);
833 LIST_FOR_EACH_ENTRY(output_data, &sprd_data->output_list, link) {
834 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
835 if (display_buffer == layer_data->display_buffer) {
836 _tdm_sprd_display_layer_disable(layer_data);
837 layer_data->display_buffer = NULL;
841 LIST_DEL(&display_buffer->link);
843 free(display_buffer);
846 tdm_sprd_output_data *
847 _tdm_sprd_display_create_output_LCD(tdm_sprd_data *sprd_data)
849 tdm_sprd_output_data *output_data = NULL;
850 tdm_error ret = TDM_ERROR_NONE;
852 output_data = calloc(1, sizeof(tdm_sprd_output_data));
854 TDM_ERR("alloc failed");
858 output_data->sprd_data = sprd_data;
859 output_data->pipe = 0;
860 output_data->connector_type = TDM_OUTPUT_TYPE_LVDS;
861 output_data->count_modes = 0;
862 output_data->fb_fd_name = FB_DEV_LCD;
863 LIST_INITHEAD(&output_data->layer_list);
865 ret = _tdm_sprd_display_output_update(output_data);
866 if (ret != TDM_ERROR_NONE) {
867 TDM_ERR("_tdm_sprd_display_output_update failed (%d)", ret);
872 if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED) {
873 //LCD has only one mode
874 output_data->count_modes = 1;
875 output_data->output_modes = calloc(output_data->count_modes, sizeof(tdm_output_mode));
876 if (!output_data->output_modes) {
877 TDM_ERR("alloc failed");
878 if (output_data->fb_fd > 0)
879 close(output_data->fb_fd);
883 _tdm_sprd_display_to_tdm_mode(&output_data->mi, &output_data->output_modes[0]);
885 output_data->status = TDM_OUTPUT_CONN_STATUS_MODE_SETTED;
888 TDM_DBG("output(%p, status:%d type:%d-%d) pipe(%d) dpms(%d)", output_data, output_data->status,
889 output_data->connector_type, output_data->connector_type_id, output_data->pipe, output_data->dpms_value);
891 ret = _tdm_sprd_display_create_layer_list_LCD(output_data);
892 if (ret != TDM_ERROR_NONE) {
893 TDM_ERR("_tdm_sprd_display_create_layer_list_LCD failed (%d)", ret);
894 if (output_data->fb_fd > 0)
895 close(output_data->fb_fd);
896 free(output_data->output_modes);
901 LIST_INITHEAD(&output_data->capture_list);
906 tdm_sprd_layer_data *
907 _sprd_output_get_layer(tdm_sprd_output_data *output_data, int index)
909 RETURN_VAL_IF_FAIL(output_data, NULL);
911 tdm_sprd_layer_data *l = NULL;
912 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link)
913 if (l->zpos == index)
920 _sprd_layer_attach_window(tdm_sprd_layer_data *layer_data, tdm_sprd_hwc_window_data *hwc_window_data)
922 tdm_error ret = TDM_ERROR_NONE;
924 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
926 if (hwc_window_data == NULL || hwc_window_data->display_buffer == NULL) {
927 ret = sprd_layer_unset_buffer(layer_data);
928 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
930 ret = sprd_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info));
931 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
932 RETURN_VAL_IF_FAIL(hwc_window_data->display_buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
933 ret = sprd_layer_set_buffer(layer_data, hwc_window_data->display_buffer->buffer);
934 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
940 _get_number_of_visible_windows(tdm_sprd_output_data *output_data)
943 tdm_sprd_hwc_window_data *window = NULL;
945 RETURN_VAL_IF_FAIL(output_data, 0);
947 LIST_FOR_EACH_ENTRY(window, &output_data->hwc_window_list, link) {
948 if (window->client_type == TDM_COMPOSITION_NONE)
958 _tdm_sprd_display_prepare_commit(tdm_sprd_output_data *output_data) {
960 tdm_sprd_layer_data * layer = NULL;
961 int i = HW_LAYER_NUM-1;
962 tdm_sprd_hwc_window_data *hwc_window_data = NULL;
964 RETURN_VAL_IF_FAIL(output_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
966 if (!_get_number_of_visible_windows(output_data))
967 output_data->need_target_buffer = 1;
969 /* set target hwc window */
970 if (output_data->need_target_buffer) {
971 layer = _sprd_output_get_layer(output_data, i--);
972 _sprd_layer_attach_window(layer, output_data->target_hwc_window);
975 /* set hwc windows */
976 LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &output_data->hwc_window_list, link) {
977 if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
979 if (hwc_window_data->client_type != TDM_COMPOSITION_DEVICE)
982 return TDM_ERROR_OPERATION_FAILED;
983 layer = _sprd_output_get_layer(output_data, i--);
984 _sprd_layer_attach_window(layer, hwc_window_data);
987 /* disable unused layer */
989 layer = _sprd_output_get_layer(output_data, i--);
990 _sprd_layer_attach_window(layer, NULL);
993 return TDM_ERROR_NONE;
997 tdm_sprd_display_buffer *
998 _tdm_sprd_display_creat_buffer(tdm_sprd_data *sprd_data, tbm_surface_h surface, tdm_error * err)
1002 tdm_sprd_display_buffer * display_buffer = NULL;
1003 tdm_error res = TDM_ERROR_NONE;
1005 RETURN_VAL_IF_FAIL(sprd_data, NULL);
1006 RETURN_VAL_IF_FAIL(surface, NULL);
1008 display_buffer = calloc(1, sizeof(tdm_sprd_display_buffer));
1009 if (!display_buffer) {
1011 *err = TDM_ERROR_OUT_OF_MEMORY;
1015 display_buffer->buffer = surface;
1017 res = tdm_buffer_add_destroy_handler(surface, _tdm_sprd_display_cb_destroy_buffer, sprd_data);
1018 if (res != TDM_ERROR_NONE) {
1021 TDM_ERR("add destroy handler fail");
1022 free(display_buffer);
1026 tdm_helper_get_buffer_full_size(surface, &bw, &bh);
1028 display_buffer->width = bw;
1029 display_buffer->height = bh;
1030 display_buffer->format = tbm_surface_get_format(surface);
1031 display_buffer->count = tbm_surface_internal_get_num_bos(surface);
1032 count = tbm_surface_internal_get_num_planes(display_buffer->format);
1033 TDM_DBG("create buffer: %dx%d %c%c%c%c bo_num:%d plane_num:%d",
1034 display_buffer->width, display_buffer->height, FOURCC_STR(display_buffer->format),
1035 display_buffer->count, count);
1037 for (i = 0; i < display_buffer->count; i++) {
1038 tbm_bo bo = tbm_surface_internal_get_bo(surface, i);
1039 display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
1040 display_buffer->name[i] = tbm_bo_export(bo);
1041 TDM_DBG(" create buffer: bo%d(name:%d handle:%d)", i, display_buffer->name[i],
1042 display_buffer->handles[i]);
1044 for (i = 0; i < count; i++) {
1045 tbm_surface_internal_get_plane_data(surface, i, &display_buffer->size, &display_buffer->offsets[i],
1046 &display_buffer->pitches[i]);
1047 TDM_DBG(" create buffer: plane%d(size:%d offset:%d pitch:%d)", i, display_buffer->size,
1048 display_buffer->offsets[i], display_buffer->pitches[i]);
1051 if (IS_RGB(display_buffer->format))
1052 display_buffer->width = display_buffer->pitches[0] >> 2;
1054 display_buffer->width = display_buffer->pitches[0];
1057 *err = TDM_ERROR_NONE;
1059 return display_buffer;
1063 _sprd_drm_user_handler(struct drm_event *event)
1065 RETURN_VAL_IF_FAIL(event, -1);
1067 TDM_DBG("got event %d\n", event->type);
1069 if (event->type != DRM_SPRD_IPP_EVENT)
1071 tdm_sprd_pp_handler((struct drm_sprd_ipp_event *) event);
1077 _sprd_drm_vblank_event(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1079 tdm_sprd_vblank_data *vblank_data = (tdm_sprd_vblank_data *) user_data;
1080 tdm_sprd_output_data *output_data;
1081 tdm_sprd_layer_data *layer_data = NULL;
1084 TDM_ERR("no vblank data");
1088 output_data = vblank_data->output_data;
1090 TDM_ERR("no output data");
1093 switch (vblank_data->type) {
1094 case VBLANK_TYPE_WAIT:
1095 if (output_data->vblank_func)
1096 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, vblank_data->user_data);
1098 case VBLANK_TYPE_COMMIT:
1099 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
1100 if (layer_data->need_unset) {
1101 _tdm_sprd_display_layer_disable(layer_data);
1102 layer_data->need_unset = 0;
1106 if (output_data->commit_func)
1107 output_data->commit_func(output_data, sequence, tv_sec, tv_usec, vblank_data->user_data);
1117 _sprd_drm_flip_complete_event(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1119 TDM_DBG("FLIP EVENT");
1124 _sprd_layer_is_supported_format(tdm_sprd_layer_data *layer_data, tbm_format format)
1126 RETURN_VAL_IF_FAIL(layer_data, 0);
1127 return IS_RGB(format);
1131 _sprd_hwc_window_is_reserved_buffer(tdm_sprd_hwc_window_data *hwc_window_data) {
1135 RETURN_VAL_IF_FAIL(hwc_window_data != NULL, 0);
1136 RETURN_VAL_IF_FAIL(hwc_window_data->display_buffer != NULL, 0);
1138 bo = tbm_surface_internal_get_bo(hwc_window_data->display_buffer->buffer, 0);
1139 RETURN_VAL_IF_FAIL(bo != NULL, 0);
1141 falgs = tbm_bo_get_flags(bo);
1143 return falgs & TBM_BO_SCANOUT;
1148 _sprd_output_get_changed_number(tdm_sprd_hwc_data *hwc_data)
1151 tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1153 LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
1154 if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
1157 if (hwc_window_data->client_type != hwc_window_data->validated_type)
1164 static tdm_hwc_window *
1165 _sprd_hwc_create_window(tdm_sprd_hwc_data *hwc_data, tdm_hwc_window_info *info, tdm_error *error)
1167 tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1170 *error = TDM_ERROR_NONE;
1172 hwc_window_data = calloc(1, sizeof(tdm_sprd_hwc_window_data));
1173 if (!hwc_window_data) {
1174 TDM_ERR("alloc failed");
1176 *error = TDM_ERROR_OUT_OF_MEMORY;
1180 hwc_window_data->hwc_data = hwc_data;
1183 memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
1185 LIST_INITHEAD(&hwc_window_data->link);
1187 return hwc_window_data;
1191 tdm_sprd_display_destroy_output_list(tdm_sprd_data *sprd_data)
1193 tdm_sprd_output_data *o = NULL, *oo = NULL;
1195 if (LIST_IS_EMPTY(&sprd_data->output_list))
1198 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &sprd_data->output_list, link) {
1202 if (!LIST_IS_EMPTY(&o->capture_list)) {
1203 tdm_sprd_output_capture_data *l = NULL, *ll = NULL;
1204 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->capture_list, link) {
1205 sprd_capture_destroy(l->tdm_capture_p);
1208 if (!LIST_IS_EMPTY(&o->layer_list)) {
1209 tdm_sprd_layer_data *l = NULL, *ll = NULL;
1210 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
1215 free(o->output_modes);
1221 tdm_sprd_display_create_output_list(tdm_sprd_data *sprd_data)
1223 tdm_sprd_output_data *output_data = NULL;
1225 RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&sprd_data->output_list), TDM_ERROR_OPERATION_FAILED);
1227 //have only LCD output
1228 output_data = _tdm_sprd_display_create_output_LCD(sprd_data);
1229 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_OPERATION_FAILED);
1230 LIST_ADDTAIL(&output_data->link, &sprd_data->output_list);
1231 sprd_data->output_count = 1;
1233 TDM_DBG("output count: %d", sprd_data->output_count);
1235 return TDM_ERROR_NONE;
1239 tdm_sprd_display_destroy_buffer_list(tdm_sprd_data *sprd_data)
1241 tdm_sprd_display_buffer *b = NULL, *bb = NULL;
1243 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &sprd_data->buffer_list, link) {
1244 tdm_buffer_remove_destroy_handler(b->buffer, _tdm_sprd_display_cb_destroy_buffer, sprd_data);
1245 _tdm_sprd_display_cb_destroy_buffer(b->buffer, sprd_data);
1250 sprd_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
1252 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1254 caps->max_layer_count = -1; /* not defined */
1256 return TDM_ERROR_NONE;
1260 sprd_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps)
1262 return tdm_sprd_pp_get_capability(bdata, caps);
1266 sprd_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
1268 tdm_sprd_data *sprd_data = bdata;
1269 tdm_sprd_output_data *output_data = NULL;
1270 tdm_output **outputs;
1274 RETURN_VAL_IF_FAIL(sprd_data, NULL);
1275 RETURN_VAL_IF_FAIL(count, NULL);
1278 LIST_FOR_EACH_ENTRY(output_data, &sprd_data->output_list, link)
1282 ret = TDM_ERROR_NONE;
1286 /* will be freed in frontend */
1287 outputs = calloc(*count, sizeof(tdm_sprd_output_data *));
1289 TDM_ERR("failed: alloc memory");
1291 ret = TDM_ERROR_OUT_OF_MEMORY;
1296 LIST_FOR_EACH_ENTRY(output_data, &sprd_data->output_list, link)
1297 outputs[i++] = output_data;
1300 *error = TDM_ERROR_NONE;
1310 sprd_display_get_fd(tdm_backend_data *bdata, int *fd)
1312 tdm_sprd_data *sprd_data = bdata;
1314 RETURN_VAL_IF_FAIL(sprd_data, TDM_ERROR_INVALID_PARAMETER);
1315 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
1317 *fd = sprd_data->drm_fd;
1319 return TDM_ERROR_NONE;
1323 sprd_display_handle_events(tdm_backend_data *bdata)
1325 tdm_sprd_data *sprd_data = bdata;
1326 RETURN_VAL_IF_FAIL(sprd_data, TDM_ERROR_INVALID_PARAMETER);
1328 if (drmHandleEvent(sprd_data->drm_fd, &sprd_data->evctx) < 0)
1329 return TDM_ERROR_OPERATION_FAILED;
1331 return TDM_ERROR_NONE;
1335 sprd_display_create_pp(tdm_backend_data *bdata, tdm_error *error)
1337 tdm_sprd_data *sprd_data = bdata;
1339 RETURN_VAL_IF_FAIL(sprd_data, NULL);
1341 return tdm_sprd_pp_create(sprd_data, error);
1345 sprd_output_get_capability(tdm_output *output, tdm_caps_output *caps)
1347 tdm_sprd_output_data *output_data = output;
1351 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1352 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1353 RETURN_VAL_IF_FAIL(output_data->sprd_data, TDM_ERROR_INVALID_PARAMETER);
1355 memset(caps, 0, sizeof(tdm_caps_output));
1357 snprintf(caps->maker, TDM_NAME_LEN, "unknown");
1358 snprintf(caps->model, TDM_NAME_LEN, "unknown");
1359 snprintf(caps->name, TDM_NAME_LEN, "unknown");
1361 caps->status = output_data->status;
1362 caps->type = output_data->connector_type;
1363 caps->type_id = output_data->connector_type_id;
1365 caps->mode_count = output_data->count_modes;
1366 caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count);
1368 ret = TDM_ERROR_OUT_OF_MEMORY;
1369 TDM_ERR("alloc failed\n");
1370 memset(caps, 0, sizeof(tdm_caps_output));
1373 for (i = 0; i < caps->mode_count; i++)
1374 caps->modes[i] = output_data->output_modes[i];
1376 caps->mmWidth = output_data->mi.width;
1377 caps->mmHeight = output_data->mi.height;
1382 caps->max_w = output_data->mi.xres_virtual;
1383 caps->max_h = output_data->mi.yres_virtual;
1384 caps->preferred_align = -1;
1386 caps->prop_count = 0;
1389 if (output_data->sprd_data->hwc_mode)
1390 caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
1392 return TDM_ERROR_NONE;
1396 sprd_output_get_layers(tdm_output *output, int *count, tdm_error *error)
1398 tdm_sprd_output_data *output_data = output;
1399 tdm_sprd_layer_data *layer_data = NULL;
1401 tdm_error ret = TDM_ERROR_OPERATION_FAILED;
1404 RETURN_VAL_IF_FAIL(output_data, NULL);
1405 RETURN_VAL_IF_FAIL(count, NULL);
1407 if (output_data->sprd_data->hwc_mode) {
1408 TDM_INFO("layers aren't supported in HWC mode");
1410 ret = TDM_ERROR_NONE;
1415 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1419 ret = TDM_ERROR_NONE;
1423 /* will be freed in frontend */
1424 layers = calloc(*count, sizeof(tdm_sprd_layer_data *));
1426 TDM_ERR("failed: alloc memory");
1428 ret = TDM_ERROR_OUT_OF_MEMORY;
1433 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1434 layers[i++] = layer_data;
1437 *error = TDM_ERROR_NONE;
1447 sprd_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
1449 return TDM_ERROR_NOT_IMPLEMENTED;
1453 sprd_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
1455 return TDM_ERROR_NOT_IMPLEMENTED;
1459 sprd_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data)
1461 tdm_sprd_output_data *output_data = output;
1462 tdm_sprd_data *sprd_data;
1463 tdm_sprd_vblank_data *vblank_data;
1467 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1469 vblank_data = calloc(1, sizeof(tdm_sprd_vblank_data));
1471 TDM_ERR("alloc failed");
1472 return TDM_ERROR_OUT_OF_MEMORY;
1475 sprd_data = output_data->sprd_data;
1477 ret = _tdm_sprd_display_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
1478 if (ret != TDM_ERROR_NONE)
1481 target_msc += interval;
1483 vblank_data->type = VBLANK_TYPE_WAIT;
1484 vblank_data->output_data = output_data;
1485 vblank_data->user_data = user_data;
1487 ret = _tdm_sprd_display_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
1488 if (ret != TDM_ERROR_NONE)
1491 return TDM_ERROR_NONE;
1498 sprd_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func)
1500 tdm_sprd_output_data *output_data = output;
1501 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1502 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1503 output_data->vblank_func = func;
1505 return TDM_ERROR_NONE;
1509 sprd_output_commit(tdm_output *output, int sync, void *user_data)
1511 tdm_sprd_output_data *output_data = output;
1512 tdm_sprd_data *sprd_data;
1513 tdm_error ret = TDM_ERROR_NONE;
1515 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1517 sprd_data = output_data->sprd_data;
1519 _tdm_sprd_display_do_commit(output_data);
1520 RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1522 tdm_sprd_vblank_data *vblank_data = calloc(1, sizeof(tdm_sprd_vblank_data));
1526 TDM_ERR("alloc failed");
1527 return TDM_ERROR_OUT_OF_MEMORY;
1530 ret = _tdm_sprd_display_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
1531 if (ret != TDM_ERROR_NONE) {
1538 vblank_data->type = VBLANK_TYPE_COMMIT;
1539 vblank_data->output_data = output_data;
1540 vblank_data->user_data = user_data;
1542 ret = _tdm_sprd_display_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
1543 if (ret != TDM_ERROR_NONE) {
1548 return TDM_ERROR_NONE;
1552 sprd_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func)
1554 tdm_sprd_output_data *output_data = output;
1556 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1557 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1559 output_data->commit_func = func;
1561 return TDM_ERROR_NONE;
1565 sprd_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1567 tdm_sprd_output_data *output_data = output;
1570 if (output_data->dpms_value == dpms_value)
1571 return TDM_ERROR_NONE;
1573 output_data->dpms_value = dpms_value;
1575 if (dpms_value != TDM_OUTPUT_DPMS_ON)
1576 ret = _tdm_sprd_display_output_disable(output_data);
1578 ret = _tdm_sprd_display_output_enable(output_data);
1584 sprd_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1586 RETURN_VAL_IF_FAIL(output, TDM_ERROR_INVALID_PARAMETER);
1587 RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
1589 tdm_sprd_output_data *output_data = output;
1591 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1593 *dpms_value = output_data->dpms_value;
1595 return TDM_ERROR_NONE;
1599 sprd_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1601 tdm_sprd_output_data *output_data = output;
1602 tdm_error ret = TDM_ERROR_NONE;
1604 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1605 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1606 RETURN_VAL_IF_FAIL(output_data->sprd_data, TDM_ERROR_INVALID_PARAMETER);
1608 /* create or replace the target_window when the output mode is set */
1609 if (output_data->sprd_data->hwc_mode) {
1610 ret = sprd_hwc_initailize_target_window(output_data->hwc_data, mode->hdisplay, mode->hdisplay);
1611 if (ret != TDM_ERROR_NONE) {
1612 TDM_ERR("create target hwc window failed (%d)", ret);
1617 output_data->current_mode = mode;
1618 output_data->mode_changed = 1;
1620 return TDM_ERROR_NONE;
1624 sprd_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1626 tdm_sprd_output_data *output_data = output;
1628 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1629 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1631 *mode = output_data->current_mode;
1633 return TDM_ERROR_NONE;
1637 sprd_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
1639 tdm_sprd_layer_data *layer_data = layer;
1643 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1644 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1646 memset(caps, 0, sizeof(tdm_caps_layer));
1648 caps->capabilities = layer_data->capabilities;
1649 caps->zpos = layer_data->zpos;
1651 caps->format_count = layer_data->format_count;
1652 caps->formats = calloc(1, sizeof(tbm_format) * caps->format_count);
1653 if (!caps->formats) {
1654 ret = TDM_ERROR_OUT_OF_MEMORY;
1655 TDM_ERR("alloc failed\n");
1656 memset(caps, 0, sizeof(tdm_caps_layer));
1660 for (i = 0; i < caps->format_count; i++)
1661 caps->formats[i] = layer_data->formats[i];
1663 caps->prop_count = 0;
1666 return TDM_ERROR_NONE;
1670 sprd_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1672 return TDM_ERROR_NOT_IMPLEMENTED;
1676 sprd_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1678 return TDM_ERROR_NOT_IMPLEMENTED;
1682 sprd_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1684 tdm_sprd_layer_data *layer_data = layer;
1686 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1687 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1689 layer_data->info = *info;
1690 layer_data->info_changed = 1;
1692 return TDM_ERROR_NONE;
1696 sprd_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1698 tdm_sprd_layer_data *layer_data = layer;
1700 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1701 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1703 *info = layer_data->info;
1705 return TDM_ERROR_NONE;
1709 sprd_layer_set_buffer(tdm_layer *layer, tbm_surface_h surface)
1711 tdm_sprd_layer_data *layer_data = layer;
1712 tdm_sprd_data *sprd_data;
1713 tdm_sprd_display_buffer *display_buffer;
1714 tdm_error err = TDM_ERROR_NONE;
1716 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1717 RETURN_VAL_IF_FAIL(surface, TDM_ERROR_INVALID_PARAMETER);
1719 sprd_data = layer_data->sprd_data;
1720 display_buffer = _tdm_sprd_display_find_buffer(sprd_data, surface);
1721 if (!display_buffer) {
1722 display_buffer = _tdm_sprd_display_creat_buffer(sprd_data, surface, &err);
1723 RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
1724 LIST_ADDTAIL(&display_buffer->link, &sprd_data->buffer_list);
1727 layer_data->display_buffer = display_buffer;
1728 layer_data->display_buffer_changed = 1;
1730 return TDM_ERROR_NONE;
1735 sprd_layer_unset_buffer(tdm_layer *layer)
1737 tdm_sprd_layer_data *layer_data = layer;
1738 tdm_sprd_data *sprd_data;
1740 TDM_DBG("Unset buffer");
1741 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1742 RETURN_VAL_IF_FAIL(layer_data->output_data, TDM_ERROR_INVALID_PARAMETER);
1744 sprd_data = layer_data->output_data->sprd_data;
1746 if (sprd_data->hwc_mode) {
1747 if (layer_data->display_buffer)
1748 layer_data->display_buffer_changed = 1;
1750 _tdm_sprd_display_layer_disable(layer);
1751 layer_data->display_buffer = NULL;
1753 return TDM_ERROR_NONE;
1757 sprd_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1759 tdm_sprd_layer_data *layer_data = layer;
1761 switch (layer_data->zpos) {
1764 *flags = TBM_BO_SCANOUT;
1767 return TDM_ERROR_INVALID_PARAMETER;
1770 return TDM_ERROR_NONE;
1774 tdm_sprd_display_init_event_handling(tdm_sprd_data *sprd_data)
1776 RETURN_VAL_IF_FAIL(sprd_data, TDM_ERROR_INVALID_PARAMETER);
1778 sprd_data->evctx.version = 2;
1779 sprd_data->evctx.page_flip_handler = _sprd_drm_flip_complete_event;
1780 sprd_data->evctx.vblank_handler = _sprd_drm_vblank_event;
1782 drmAddUserHandler(sprd_data->drm_fd, _sprd_drm_user_handler);
1784 return TDM_ERROR_NONE;
1788 tdm_sprd_display_deinit_event_handling(tdm_sprd_data *sprd_data)
1790 RETURN_VOID_IF_FAIL(sprd_data);
1792 drmRemoveUserHandler(sprd_data->drm_fd, _sprd_drm_user_handler);
1796 sprd_output_get_sprd_data(tdm_output *output)
1798 RETURN_VAL_IF_FAIL(output, NULL);
1799 tdm_sprd_output_data *output_data = output;
1800 return output_data->sprd_data;
1804 sprd_output_attach_capture(tdm_output *output, tdm_capture *capture)
1806 RETURN_VAL_IF_FAIL(output, TDM_ERROR_INVALID_PARAMETER);
1807 RETURN_VAL_IF_FAIL(capture, TDM_ERROR_INVALID_PARAMETER);
1809 tdm_sprd_output_capture_data *output_capture_data_p =
1810 calloc(1, sizeof(tdm_sprd_output_capture_data));
1811 RETURN_VAL_IF_FAIL(output_capture_data_p, TDM_ERROR_OUT_OF_MEMORY);
1812 tdm_sprd_output_data *output_data = output;
1813 output_capture_data_p->tdm_capture_p = capture;
1814 LIST_ADD(&output_capture_data_p->link, &output_data->capture_list);
1815 TDM_DBG("capture attached");
1816 return TDM_ERROR_NONE;
1820 sprd_output_dettach_capture(tdm_output *output, tdm_capture *capture)
1822 RETURN_VOID_IF_FAIL(output);
1823 RETURN_VOID_IF_FAIL(capture);
1825 tdm_sprd_output_data *output_data = output;
1826 if (!LIST_IS_EMPTY(&output_data->capture_list)) {
1827 tdm_sprd_output_capture_data *l = NULL, *ll = NULL;
1828 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &output_data->capture_list, link) {
1829 if (l->tdm_capture_p == capture) {
1838 sprd_layer_get_buffer(tdm_layer *layer, tbm_surface_h *surface)
1840 tdm_sprd_layer_data *layer_data = layer;
1841 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1842 if (!layer_data->display_buffer) {
1846 return TDM_ERROR_NONE;
1849 *surface = layer_data->display_buffer->buffer;
1851 return TDM_ERROR_NONE;
1855 sprd_layer_get_zpos(tdm_layer *layer, int *zpos)
1857 tdm_sprd_layer_data *layer_data = layer;
1858 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1860 *zpos = layer_data->zpos;
1862 return TDM_ERROR_NONE;
1866 sprd_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
1868 tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1869 tdm_sprd_hwc_data *hwc_data = hwc;
1871 RETURN_VAL_IF_FAIL(hwc_data, NULL);
1873 hwc_window_data = _sprd_hwc_create_window(hwc_data, NULL, error);
1874 RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
1876 LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
1878 TDM_DBG("hwc_window(%p) create", hwc_window_data);
1880 *error = TDM_ERROR_NONE;
1882 return hwc_window_data;
1886 sprd_hwc_window_destroy(tdm_hwc_window *hwc_window)
1888 tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
1890 if (!hwc_window_data)
1893 LIST_DEL(&hwc_window_data->link);
1895 free(hwc_window_data);
1899 sprd_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
1901 tdm_sprd_hwc_data *hwc_data = hwc;
1902 tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1904 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
1905 RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
1907 /* decide the validated_types with client_types */
1908 LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
1909 /* set the none to validated_type */
1910 if (hwc_window_data->client_type == TDM_COMPOSITION_NONE &&
1911 hwc_window_data->validated_type != TDM_COMPOSITION_NONE) {
1912 hwc_window_data->validated_type = TDM_COMPOSITION_NONE;
1916 /* all hwc_windows make TDM_COMPOSITION_CLIENT */
1917 if (hwc_window_data->client_type != TDM_COMPOSITION_CLIENT) {
1918 hwc_window_data->validated_type = TDM_COMPOSITION_CLIENT;
1923 LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
1924 if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
1927 TDM_DBG(" window(%p) type: %s -> %s", hwc_window_data,
1928 _comp_to_str(hwc_window_data->client_type),
1929 _comp_to_str(hwc_window_data->validated_type));
1932 /* The driver always needs the target_buffer */
1933 hwc_data->need_target_window = 1;
1935 *num_types = _sprd_output_get_changed_number(hwc_data);
1936 if (*num_types == 0)
1937 hwc_data->need_validate = 0;
1939 return TDM_ERROR_NONE;
1943 sprd_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
1944 tdm_hwc_window **hwc_window, tdm_hwc_window_composition *composition_types)
1946 tdm_sprd_hwc_data *hwc_data = hwc;
1949 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
1950 RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
1952 if ((hwc_window == NULL) || (composition_types == NULL)) {
1953 *num_elements = _sprd_output_get_changed_number(hwc_data);
1954 return TDM_ERROR_NONE;
1957 tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1958 LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
1959 if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
1962 if (num >= *num_elements)
1965 if (hwc_window_data->client_type != hwc_window_data->validated_type) {
1966 composition_types[num] = hwc_window_data->validated_type;
1967 hwc_window[num] = hwc_window_data;
1972 /* set real num of changed composition types */
1973 *num_elements = num;
1975 return TDM_ERROR_NONE;
1979 sprd_hwc_accept_changes(tdm_hwc *hwc)
1981 tdm_sprd_hwc_data *hwc_data = hwc;
1983 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
1985 tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1986 LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
1987 if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
1990 hwc_window_data->client_type = hwc_window_data->validated_type;
1993 hwc_data->need_validate = 0;
1995 return TDM_ERROR_NONE;
1999 sprd_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
2001 tdm_sprd_hwc_data *hwc_data = hwc;
2002 tbm_surface_queue_h tqueue = NULL;
2005 *error = TDM_ERROR_INVALID_PARAMETER;
2007 RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
2009 if (hwc_data->target_hwc_window == NULL) {
2011 *error = TDM_ERROR_OPERATION_FAILED;
2015 tqueue = _sprd_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
2016 RETURN_VAL_IF_FAIL(tqueue, NULL);
2019 *error = TDM_ERROR_NONE;
2024 sprd_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
2026 tdm_sprd_hwc_data *hwc_data = hwc;
2029 /* TODO: as the sprd-driver currently doesn't support DEVICE to CLIENT transition.
2030 * we silence skip 'composited_wnds' */
2032 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2033 RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED);
2035 err = sprd_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
2036 RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
2038 err = sprd_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
2039 RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
2041 return TDM_ERROR_NONE;
2045 sprd_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
2047 RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
2048 RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
2049 RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
2051 // TODO: fix these formats.
2052 *formats = hwc_window_video_formats;
2053 *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
2055 return TDM_ERROR_NONE;
2059 sprd_hwc_get_video_capability(tdm_hwc *hwc, tdm_hwc_video_capability *video_capability)
2061 RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
2062 RETURN_VAL_IF_FAIL(video_capability != NULL, TDM_ERROR_INVALID_PARAMETER);
2064 *video_capability = TDM_HWC_VIDEO_CAPABILITY_SCANOUT;
2066 return TDM_ERROR_NONE;
2070 sprd_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
2072 tdm_sprd_hwc_data *hwc_data = hwc;
2074 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2078 return TDM_ERROR_NONE;
2082 sprd_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
2083 tdm_hwc_window_composition comp_type)
2085 tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2086 tdm_sprd_hwc_data *hwc_data = hwc_window_data->hwc_data;
2088 RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2089 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2091 if (hwc_window_data->client_type == comp_type)
2092 return TDM_ERROR_NONE;
2094 hwc_window_data->client_type = comp_type;
2096 hwc_data->need_validate = 1;
2098 return TDM_ERROR_NONE;
2103 sprd_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage)
2105 tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2107 RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2111 return TDM_ERROR_NONE;
2115 sprd_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
2117 tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2118 tdm_sprd_hwc_data *hwc_data = hwc_window_data->hwc_data;
2120 RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2121 RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2122 RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
2124 if (memcmp(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info)) == 0)
2125 return TDM_ERROR_NONE;
2127 hwc_window_data->info = *info;
2128 hwc_data->need_validate = 1;
2130 return TDM_ERROR_NONE;
2134 sprd_hwc_window_get_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
2136 tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2138 RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2139 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
2141 *info = hwc_window_data->info;
2143 return TDM_ERROR_NONE;
2147 sprd_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
2149 tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2150 tdm_sprd_hwc_data *hwc_data;
2151 tdm_sprd_output_data *output_data;
2152 tdm_sprd_data *sprd_data;
2153 tdm_error err = TDM_ERROR_OPERATION_FAILED;
2155 tdm_sprd_display_buffer *display_buffer = NULL;
2157 RETURN_VAL_IF_FAIL(hwc_window_data != NULL, err);
2158 hwc_data = hwc_window_data->hwc_data;
2159 RETURN_VAL_IF_FAIL(hwc_data != NULL, err);
2160 output_data = hwc_data->output_data;
2161 RETURN_VAL_IF_FAIL(hwc_data != NULL, err);
2162 sprd_data = output_data->sprd_data;
2163 RETURN_VAL_IF_FAIL(sprd_data != NULL, err);
2166 hwc_window_data->display_buffer = NULL;
2167 return TDM_ERROR_NONE;
2170 display_buffer = _tdm_sprd_display_find_buffer(sprd_data, surface);
2171 if (!display_buffer) {
2172 display_buffer = _tdm_sprd_display_creat_buffer(sprd_data, surface, &err);
2173 RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
2174 LIST_ADDTAIL(&display_buffer->link, &sprd_data->buffer_list);
2177 if (hwc_window_data->display_buffer == display_buffer)
2178 return TDM_ERROR_NONE;
2180 hwc_window_data->display_buffer = display_buffer;
2182 return TDM_ERROR_NONE;
2186 sprd_hwc_initailize_target_window(tdm_hwc *hwc, int width, int height)
2188 tdm_hwc_window_info info = {0};
2189 tdm_error ret = TDM_ERROR_NONE;
2190 tdm_sprd_hwc_window_data *target_hwc_window;
2191 tdm_sprd_hwc_data *hwc_data = hwc;
2193 RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
2197 info.dst_pos.h = height;
2198 info.dst_pos.w = width;
2200 info.src_config.pos.x = 0;
2201 info.src_config.pos.y = 0;
2202 info.src_config.pos.h = height;
2203 info.src_config.pos.w = width;
2205 info.src_config.size.h = width;
2206 info.src_config.size.v = height;
2207 info.src_config.format = TBM_FORMAT_ARGB8888;
2209 target_hwc_window = _sprd_hwc_create_window(hwc_data, &info, &ret);
2210 if (ret != TDM_ERROR_NONE) {
2211 TDM_ERR("create target hwc window failed (%d)", ret);
2212 return TDM_ERROR_OPERATION_FAILED;
2215 if (hwc_data->target_hwc_window)
2216 sprd_hwc_window_destroy(hwc_data->target_hwc_window);
2218 hwc_data->target_hwc_window = target_hwc_window;
2219 hwc_data->need_set_crtc = 1;
2221 return TDM_ERROR_NONE;
2225 sprd_output_get_hwc(tdm_output *output, tdm_error *error)
2227 tdm_sprd_hwc_data *hwc_data = NULL;
2228 tdm_sprd_output_data *output_data = output;
2231 TDM_ERR("invalid params");
2233 *error = TDM_ERROR_INVALID_PARAMETER;
2237 if (output_data->hwc_data) {
2238 TDM_INFO("hwc_data already exists");
2240 *error = TDM_ERROR_NONE;
2241 return output_data->hwc_data;
2244 hwc_data = calloc(1, sizeof(tdm_sprd_hwc_data));
2246 TDM_ERR("alloc failed");
2248 *error = TDM_ERROR_OUT_OF_MEMORY;
2251 hwc_data->output_data = output_data;
2253 LIST_INITHEAD(&hwc_data->hwc_window_list);
2255 output_data->hwc_data = hwc_data;
2258 *error = TDM_ERROR_NONE;
2264 sprd_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
2268 return TDM_ERROR_NONE;
2272 sprd_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
2274 tdm_sprd_hwc_data *hwc_data = hwc;
2276 RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
2277 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
2279 hwc_data->commit_func = func;
2281 return TDM_ERROR_NONE;
2285 sprd_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value)
2287 tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2289 RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2293 return TDM_ERROR_NONE;
2297 sprd_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value)
2299 tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2301 RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2305 return TDM_ERROR_NONE;