hwc: added backend function of video
[platform/adaptation/spreadtrum/libtdm-sprd.git] / src / tdm_sprd_display.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <tdm_helper.h>
6 #include <linux/fb.h>
7 #include <drm.h>
8 #include <video/sprdfb.h>
9 #include <tbm_surface.h>
10 #include <tbm_surface_queue.h>
11 #include "tdm_sprd.h"
12
13 #define MIN_WIDTH   32
14 #ifdef HAVE_FB_VBLANK
15 /** @TODO fb event struct */
16 #else
17 typedef struct drm_event hw_event_t;
18 #endif
19
20 #define FB_DEV_LCD  "/dev/fb0"
21
22 #define HW_LAYER_NUM  2
23
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);
29
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;
35
36 typedef enum {
37         VBLANK_TYPE_WAIT,
38         VBLANK_TYPE_COMMIT,
39 } vblank_type_t;
40
41 struct _tdm_sprd_vblank_data_s {
42         vblank_type_t type;
43         tdm_sprd_output_data *output_data;
44         void *user_data;
45 };
46
47 typedef struct _tdm_sprd_display_buffer {
48         struct list_head link;
49
50         unsigned int fb_id;
51         tbm_surface_h buffer;
52         int width;
53         unsigned int height;
54         unsigned int format;
55         unsigned int handles[4];
56         unsigned int name[4];
57         unsigned int pitches[4];
58         unsigned int offsets[4];
59         unsigned int size;
60         unsigned int count;
61 } tdm_sprd_display_buffer;
62
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;
67
68 struct _tdm_sprd_output_data {
69         struct list_head link;
70
71         /* data which are fixed at initializing */
72         tdm_sprd_data *sprd_data;
73         uint32_t pipe;
74         int count_modes;
75         tdm_output_mode *output_modes;
76         tdm_output_type connector_type;
77         unsigned int connector_type_id;
78         struct list_head layer_list;
79
80         tdm_output_vblank_handler vblank_func;
81         tdm_output_commit_handler commit_func;
82         tdm_output_conn_status status;
83
84         int mode_changed;
85         const tdm_output_mode *current_mode;
86
87         int waiting_vblank_event;
88
89         char *fb_fd_name;
90         int fb_fd;
91
92         struct fb_var_screeninfo mi;
93
94         tdm_output_dpms dpms_value;
95
96         struct list_head capture_list;
97
98         /* hwc data */
99         tdm_sprd_hwc_data *hwc_data;
100 };
101
102 struct _tdm_sprd_layer_data {
103         struct list_head link;
104
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;
109         int zpos;
110
111         //list of sprd formats
112         int format_count;
113         tbm_format *formats;
114
115         /* not fixed data below */
116         tdm_info_layer info;
117         int info_changed;
118
119         tdm_sprd_display_buffer *display_buffer;
120         int display_buffer_changed;
121         /* current hw overlay setting */
122         overlay_info ovi;
123         int enabled_flag;
124
125         int need_unset;
126 };
127
128 struct _tdm_sprd_hwc_data {
129         tdm_sprd_hwc_window_data *target_hwc_window;
130
131         int need_validate;
132         int need_target_window;
133         int need_set_crtc;
134
135         int target_window_zpos;
136
137         tdm_sprd_output_data *output_data;
138         struct list_head hwc_window_list;
139
140         tdm_hwc_commit_handler commit_func;
141 };
142
143 struct _tdm_sprd_hwc_window_data {
144         struct list_head link;
145
146         /* data which are fixed at initializing */
147         tdm_sprd_hwc_data *hwc_data;
148
149         /* not fixed data below */
150         tdm_hwc_window_info info;
151         int info_changed;
152
153         tdm_sprd_display_buffer *display_buffer;
154         int display_buffer_changed;
155         int enabled_flag;
156
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;
161
162         tdm_hwc_window_flag flags;
163 };
164
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);
170 } Drm_Event_Context;
171
172 tbm_format img_layer_formats[] = {
173         TBM_FORMAT_NV12,
174         TBM_FORMAT_YUV420
175 };
176
177 tbm_format osd_layer_formats[] = {
178         TBM_FORMAT_RGB565,
179         TBM_FORMAT_XRGB8888,
180         TBM_FORMAT_ARGB8888
181 };
182
183 tbm_format hwc_window_video_formats[] = {
184         TBM_FORMAT_RGB565,
185         TBM_FORMAT_XRGB8888,
186         TBM_FORMAT_ARGB8888,
187         TBM_FORMAT_NV12,
188         TBM_FORMAT_YUV420
189 };
190
191 static const char *
192 _comp_to_str(tdm_hwc_window_composition composition_type)
193 {
194         if (composition_type == TDM_COMPOSITION_CLIENT)
195                 return "CLIENT";
196         else if (composition_type == TDM_COMPOSITION_DEVICE)
197                 return "DEVICE";
198         else if (composition_type == TDM_COMPOSITION_CURSOR)
199                 return "CURSOR";
200         else if (composition_type == TDM_COMPOSITION_NONE)
201                 return "NONE";
202
203         return "unknown";
204 }
205
206 static tbm_surface_queue_h
207 _sprd_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
208 {
209         tdm_sprd_hwc_window_data *hwc_window_data = NULL;
210         tbm_surface_queue_h tqueue = NULL;
211
212         if (error)
213                 *error = TDM_ERROR_INVALID_PARAMETER;
214
215         RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
216         hwc_window_data = hwc_window;
217
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;
221
222         tqueue = tbm_surface_queue_create(3, wight, hight, format, TBM_BO_SCANOUT);
223         if (error)
224                 *error = TDM_ERROR_OPERATION_FAILED;
225         RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
226
227         if (error)
228                 *error = TDM_ERROR_NONE;
229
230         return tqueue;
231 }
232
233 #if 0
234 static tdm_error
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)
239 {
240         int start, end, diff;
241         int virtual_screen;
242
243         *new_src_x = src_x;
244         *new_src_w = src_w;
245         *new_dst_x = dst_x;
246         *new_dst_w = dst_w;
247
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;
251         }
252
253         if (src_x > dst_x || ((dst_x - src_x) + buf_w) > output_w)
254                 virtual_screen = 1;
255         else
256                 virtual_screen = 0;
257
258         start = (dst_x < 0) ? 0 : dst_x;
259         end = ((dst_x + dst_w) > output_w) ? output_w : (dst_x + dst_w);
260
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;
265         }
266
267         if (!virtual_screen) {
268                 /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */
269                 if ((end - start) % 2)
270                         end--;
271         } else {
272                 /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */
273                 if (end % 2)
274                         end--;
275         }
276
277         *new_dst_x = start;
278         *new_dst_w = end - start;
279         *new_src_w = *new_dst_w;
280         diff = start - dst_x;
281         *new_src_x += diff;
282
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);
285
286         if (src_x != *new_src_x || src_w != *new_src_w || dst_x != *new_dst_x ||
287                         dst_w != *new_dst_w)
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,
290                         end);
291
292         return TDM_ERROR_NONE;
293 }
294 #endif
295
296
297 static tdm_sprd_display_buffer *
298 _tdm_sprd_display_find_buffer(tdm_sprd_data *sprd_data, tbm_surface_h buffer)
299 {
300         tdm_sprd_display_buffer *display_buffer = NULL;
301
302         LIST_FOR_EACH_ENTRY(display_buffer, &sprd_data->buffer_list, link) {
303                 if (display_buffer->buffer == buffer)
304                         return display_buffer;
305         }
306
307         return NULL;
308 }
309
310 static inline uint32_t
311 _get_refresh(struct fb_var_screeninfo *timing)
312 {
313         uint32_t pixclock, hfreq, htotal, vtotal;
314
315         pixclock = PICOS2KHZ(timing->pixclock) * 1000;
316
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;
319
320         if (timing->vmode & FB_VMODE_INTERLACED)
321                 vtotal /= 2;
322         if (timing->vmode & FB_VMODE_DOUBLE)
323                 vtotal *= 2;
324
325         hfreq = pixclock / htotal;
326         return hfreq / vtotal;
327 }
328
329 /*
330  * Convert fb_var_screeninfo to tdm_output_mode
331  */
332 static inline void
333 _tdm_sprd_display_to_tdm_mode(struct fb_var_screeninfo *timing, tdm_output_mode *mode)
334 {
335
336         if (!timing->pixclock)
337                 return;
338
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;
345
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;
350
351         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
352
353         if (timing->vmode & FB_VMODE_INTERLACED)
354                 mode->flags |= DRM_MODE_FLAG_INTERLACE;
355
356         if (timing->vmode & FB_VMODE_DOUBLE)
357                 mode->flags |= DRM_MODE_FLAG_DBLSCAN;
358
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" : "");
361 }
362
363 static int
364 _localdrmWaitVBlank(int fd, drmVBlank *vbl)
365 {
366         struct timespec timeout = {0, }, cur = {0, };
367         int ret;
368
369         ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
370         if (ret < 0) {
371                 TDM_ERR("clock_gettime failed: %s", strerror(errno));
372                 goto out;
373         }
374         timeout.tv_sec++;
375
376         do {
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)) {
383                                 errno = EBUSY;
384                                 ret = -1;
385                                 break;
386                         }
387                 }
388         } while (ret && errno == EINTR);
389
390 out:
391
392         return ret;
393 }
394
395 static tdm_error
396 _tdm_sprd_display_get_cur_msc(int fd, int pipe, uint *msc)
397 {
398         drmVBlank vbl;
399
400         vbl.request.type = DRM_VBLANK_RELATIVE;
401         if (pipe > 0)
402                 vbl.request.type |= DRM_VBLANK_SECONDARY;
403
404         vbl.request.sequence = 0;
405         if (_localdrmWaitVBlank(fd, &vbl)) {
406                 TDM_ERR("get vblank counter failed: %m");
407                 *msc = 0;
408                 return TDM_ERROR_OPERATION_FAILED;
409         }
410
411         *msc = vbl.reply.sequence;
412
413         return TDM_ERROR_NONE;
414 }
415
416 static tdm_error
417 _tdm_sprd_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
418 {
419         drmVBlank vbl;
420
421         vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
422         if (pipe > 0)
423                 vbl.request.type |= DRM_VBLANK_SECONDARY;
424
425         vbl.request.sequence = *target_msc;
426         vbl.request.signal = (unsigned long) (uintptr_t) data;
427
428         if (_localdrmWaitVBlank(fd, &vbl)) {
429                 *target_msc = 0;
430                 TDM_ERR("wait vblank failed: %m");
431                 return TDM_ERROR_OPERATION_FAILED;
432         }
433
434         *target_msc = vbl.reply.sequence;
435
436         return TDM_ERROR_NONE;
437 }
438
439 static tdm_error
440 _tdm_sprd_display_output_disable(tdm_sprd_output_data *output_data)
441 {
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));
445
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;
450         }
451         return TDM_ERROR_NONE;
452 }
453
454 static tdm_error
455 _tdm_sprd_display_output_enable(tdm_sprd_output_data *output_data)
456 {
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));
461         }
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;
465         }
466         return TDM_ERROR_NONE;
467 }
468
469 static tdm_error
470 _tdm_sprd_display_layer_disable(tdm_layer *layer)
471 {
472         tdm_sprd_layer_data *layer_data = layer;
473         int layer_index = 0;
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;
479         } else {
480                 TDM_ERR("layer capability (0x%x) not supported\n", layer_data->capabilities);
481                 return TDM_ERROR_OPERATION_FAILED;
482         }
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));
487
488                 memset(&layer_data->ovi, 0, sizeof(overlay_info));
489                 layer_data->enabled_flag = 0;
490         }
491         return TDM_ERROR_NONE;
492 }
493
494 static tdm_error
495 _tdm_sprd_tbmformat_to_sprdformat(int tbm_format, overlay_info *ovi)
496 {
497         ovi->rb_switch = 0;
498         ovi->data_type = 0;
499         ovi->endian.y = 0;
500         ovi->endian.u = 0;
501         ovi->endian.v = 0;
502
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;
508                 break;
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;
514                 break;
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;
519                 break;
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;
525                 break;
526         default:
527                 return TDM_ERROR_INVALID_PARAMETER;
528         }
529         return TDM_ERROR_NONE;
530 }
531
532 static tdm_error
533 _tdm_sprd_display_do_commit(tdm_sprd_output_data *output_data)
534 {
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};
539         int layer_index = 0;
540
541         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_OPERATION_FAILED);
542 #if 0
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);
546         }
547 #endif
548         LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
549         {
550                 if (!layer_data->display_buffer_changed && !layer_data->info_changed)
551                         continue;
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;
557                         } else {
558                                 TDM_ERR("layer capability (0x%x) not supported\n", layer_data->capabilities);
559                                 continue;
560                         }
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));
568                                 continue;
569                         }
570
571                         ovi.layer_index = layer_index;
572                         ovi.size.hsize = layer_data->display_buffer->width;
573                         ovi.size.vsize = layer_data->display_buffer->height;
574
575                         ovi.rect.x = layer_data->info.dst_pos.x;
576                         ovi.rect.y = layer_data->info.dst_pos.y;
577
578                         //restrict width
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;
582
583                         ovi.rect.w = (width + x) <= output_width ? width : output_width - x;
584                         ovi.rect.h = layer_data->info.src_config.pos.h;
585
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];
590
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));
596                                         continue;
597                                 }
598                                 memcpy(&layer_data->ovi, &ovi, sizeof(overlay_info));
599                         }
600                         layer_data->enabled_flag = 1;
601                         ov_disp.layer_index |= layer_index;
602                 } else {
603                         tdm_sprd_data *sprd_data = output_data->sprd_data;
604
605                         if (sprd_data->hwc_mode)
606                                 layer_data->need_unset = 1;
607                         else
608                                 _tdm_sprd_display_layer_disable(layer_data);
609                 }
610
611                 layer_data->display_buffer_changed = layer_data->info_changed = 0;
612         }
613
614         if (ov_disp.layer_index) {
615                 ov_disp.display_mode = SPRD_DISPLAY_OVERLAY_SYNC;
616
617                 TDM_DBG("SPRD_FB_DISPLAY_OVERLAY(%d) osd_handle:%d img_handle:%d\n", ov_disp.layer_index, ov_disp.osd_handle,
618                                 ov_disp.img_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;
622                 } else {
623                         //save enable layers
624 //                      enable_layers |= ov_disp.layer_index;
625                 }
626         }
627
628         return res;
629 }
630
631 #if 0
632 static void
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,
635                                                 void *user_data)
636 {
637         tdm_sprd_pp_handler(prop_id, buf_idx, tv_sec, tv_usec, user_data);
638 }
639 #endif
640
641 #if 0
642 static int
643 _tdm_sprd_display_events_handle(int fd, Drm_Event_Context *evctx)
644 {
645 #define MAX_BUF_SIZE    1024
646
647         char buffer[MAX_BUF_SIZE];
648         unsigned int len, i;
649         struct drm_event *e;
650
651         /* The DRM read semantics guarantees that we always get only
652          * complete events. */
653         len = read(fd, buffer, sizeof buffer);
654         if (len == 0) {
655                 TDM_WRN("warning: the size of the drm_event is 0.");
656                 return 0;
657         }
658         if (len < sizeof * e) {
659                 TDM_WRN("warning: the size of the drm_event is less than drm_event structure.");
660                 return -1;
661         }
662 #if 0
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.");
665                 return -1;
666         }
667 #endif
668         i = 0;
669         while (i < len) {
670                 e = (struct drm_event *) &buffer[i];
671                 switch (e->type) {
672                 case DRM_EVENT_VBLANK: {
673                         struct drm_event_vblank *vblank;
674
675                         if (evctx->vblank_handler == NULL)
676                                 break;
677
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 *******...");
684                 }
685                 break;
686 #if 0
687                 case DRM_EXYNOS_IPP_EVENT: {
688                         struct drm_sprd_ipp_event *ipp;
689
690                         if (evctx->pp_handler == NULL)
691                                 break;
692
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 *******...");
699                 }
700 #endif
701                 break;
702                 case DRM_EVENT_FLIP_COMPLETE:
703                         /* do nothing for flip complete */
704                         break;
705                 default:
706                         break;
707                 }
708                 i += e->length;
709         }
710
711         return 0;
712 }
713 #endif
714
715 static tdm_error
716 _tdm_sprd_display_create_layer_list_LCD(tdm_sprd_output_data *output_data)
717 {
718         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
719
720         tdm_sprd_data *sprd_data = output_data->sprd_data;
721         tdm_sprd_layer_data *layer_data_osd, *layer_data_img;
722
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;
727         }
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;
733         }
734
735         /* create OSD layer */
736         layer_data_osd->sprd_data = sprd_data;
737         layer_data_osd->output_data = output_data;
738
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;
745
746         layer_data_osd->format_count = sizeof(osd_layer_formats) / sizeof(int);
747         layer_data_osd->formats = osd_layer_formats;
748
749         TDM_DBG("layer_data_osd(%p) capabilities(0x%x)", layer_data_osd, layer_data_osd->capabilities);
750
751         LIST_ADDTAIL(&layer_data_osd->link, &output_data->layer_list);
752
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;
762
763         layer_data_img->format_count = sizeof(img_layer_formats) / sizeof(int);
764         layer_data_img->formats = img_layer_formats;
765
766         TDM_DBG("layer_data_img(%p) capabilities(0x%x)", layer_data_img, layer_data_img->capabilities);
767
768         LIST_ADDTAIL(&layer_data_img->link, &output_data->layer_list);
769
770         return TDM_ERROR_NONE;
771 }
772
773 tdm_error
774 _tdm_sprd_display_output_update(tdm_sprd_output_data *output)
775 {
776         RETURN_VAL_IF_FAIL(output, TDM_ERROR_INVALID_PARAMETER);
777         RETURN_VAL_IF_FAIL(output->fb_fd_name, TDM_ERROR_INVALID_PARAMETER);
778
779         if (!output->fb_fd)
780                 output->fb_fd = open(output->fb_fd_name, O_RDWR, 0);
781
782         if (output->fb_fd < 0)
783                 goto failed;
784
785         if (ioctl(output->fb_fd, FBIOGET_VSCREENINFO, &output->mi) == -1)
786                 goto failed;
787
788         output->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
789
790         if (output->mi.activate & FB_ACTIVATE_VBL)
791                 output->dpms_value = TDM_OUTPUT_DPMS_ON;
792         else
793                 output->dpms_value = TDM_OUTPUT_DPMS_OFF;
794
795         return TDM_ERROR_NONE;
796
797 failed:
798
799         if (output->fb_fd > 0) {
800                 close(output->fb_fd);
801                 output->fb_fd = 0;
802         }
803         output->dpms_value = TDM_OUTPUT_DPMS_OFF;
804         output->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
805         return TDM_ERROR_OPERATION_FAILED;
806 }
807
808 static void
809 _tdm_sprd_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
810 {
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;
815         if (!user_data) {
816                 TDM_ERR("no user_data");
817                 return;
818         }
819         if (!buffer) {
820                 TDM_ERR("no buffer");
821                 return;
822         }
823
824         sprd_data = (tdm_sprd_data *) user_data;
825
826         display_buffer = _tdm_sprd_display_find_buffer(sprd_data, buffer);
827         if (!display_buffer) {
828                 TDM_ERR("no display_buffer");
829                 return;
830         }
831         TDM_DBG("destroy buffer handle:%d", display_buffer->name[0]);
832
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;
838                         }
839                 }
840         }
841         LIST_DEL(&display_buffer->link);
842
843         free(display_buffer);
844 }
845
846 tdm_sprd_output_data *
847 _tdm_sprd_display_create_output_LCD(tdm_sprd_data *sprd_data)
848 {
849         tdm_sprd_output_data *output_data = NULL;
850         tdm_error ret = TDM_ERROR_NONE;
851
852         output_data = calloc(1, sizeof(tdm_sprd_output_data));
853         if (!output_data) {
854                 TDM_ERR("alloc failed");
855                 return NULL;
856         }
857
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);
864
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);
868                 free(output_data);
869                 return NULL;
870         }
871
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);
880                         free(output_data);
881                         return NULL;
882                 }
883                 _tdm_sprd_display_to_tdm_mode(&output_data->mi, &output_data->output_modes[0]);
884
885                 output_data->status = TDM_OUTPUT_CONN_STATUS_MODE_SETTED;
886         }
887
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);
890
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);
897                 free(output_data);
898                 return NULL;
899         }
900
901         LIST_INITHEAD(&output_data->capture_list);
902
903         return output_data;
904 }
905
906 tdm_sprd_layer_data *
907 _sprd_output_get_layer(tdm_sprd_output_data *output_data, int index)
908 {
909         RETURN_VAL_IF_FAIL(output_data, NULL);
910
911         tdm_sprd_layer_data *l = NULL;
912         LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link)
913                 if (l->zpos == index)
914                         return l;
915         return NULL;
916 }
917
918 #if 0
919 static tdm_error
920 _sprd_layer_attach_window(tdm_sprd_layer_data *layer_data, tdm_sprd_hwc_window_data *hwc_window_data)
921 {
922         tdm_error ret = TDM_ERROR_NONE;
923
924         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
925
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);
929         } else {
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);
935         }
936         return ret;
937 }
938
939 static int
940 _get_number_of_visible_windows(tdm_sprd_output_data *output_data)
941 {
942         int number = 0;
943         tdm_sprd_hwc_window_data *window = NULL;
944
945         RETURN_VAL_IF_FAIL(output_data, 0);
946
947         LIST_FOR_EACH_ENTRY(window, &output_data->hwc_window_list, link) {
948                 if (window->client_type == TDM_COMPOSITION_NONE)
949                         continue;
950
951                 number++;
952         }
953
954         return number;
955 }
956
957 static tdm_error
958 _tdm_sprd_display_prepare_commit(tdm_sprd_output_data *output_data) {
959
960         tdm_sprd_layer_data * layer = NULL;
961         int i = HW_LAYER_NUM-1;
962         tdm_sprd_hwc_window_data *hwc_window_data = NULL;
963
964         RETURN_VAL_IF_FAIL(output_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
965
966         if (!_get_number_of_visible_windows(output_data))
967                 output_data->need_target_buffer = 1;
968
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);
973         }
974
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)
978                         continue;
979                 if (hwc_window_data->client_type != TDM_COMPOSITION_DEVICE)
980                         continue;
981                 if (i < 0)
982                         return TDM_ERROR_OPERATION_FAILED;
983                 layer = _sprd_output_get_layer(output_data, i--);
984                 _sprd_layer_attach_window(layer, hwc_window_data);
985         }
986
987         /* disable unused layer */
988         while (i >= 0) {
989                 layer = _sprd_output_get_layer(output_data, i--);
990                 _sprd_layer_attach_window(layer, NULL);
991         }
992
993         return TDM_ERROR_NONE;
994 }
995 #endif
996
997 tdm_sprd_display_buffer *
998 _tdm_sprd_display_creat_buffer(tdm_sprd_data *sprd_data, tbm_surface_h surface, tdm_error * err)
999 {
1000         int i, count;
1001         int bw, bh;
1002         tdm_sprd_display_buffer * display_buffer = NULL;
1003         tdm_error res = TDM_ERROR_NONE;
1004
1005         RETURN_VAL_IF_FAIL(sprd_data, NULL);
1006         RETURN_VAL_IF_FAIL(surface, NULL);
1007
1008         display_buffer = calloc(1, sizeof(tdm_sprd_display_buffer));
1009         if (!display_buffer) {
1010                 if (err)
1011                         *err = TDM_ERROR_OUT_OF_MEMORY;
1012                 return NULL;
1013         }
1014
1015         display_buffer->buffer = surface;
1016
1017         res = tdm_buffer_add_destroy_handler(surface, _tdm_sprd_display_cb_destroy_buffer, sprd_data);
1018         if (res != TDM_ERROR_NONE) {
1019                 if (err)
1020                         *err = res;
1021                 TDM_ERR("add destroy handler fail");
1022                 free(display_buffer);
1023                 return NULL;
1024         }
1025
1026         tdm_helper_get_buffer_full_size(surface, &bw, &bh);
1027
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);
1036
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]);
1043         }
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]);
1049         }
1050
1051         if (IS_RGB(display_buffer->format))
1052                 display_buffer->width = display_buffer->pitches[0] >> 2;
1053         else
1054                 display_buffer->width = display_buffer->pitches[0];
1055
1056         if (err)
1057                 *err = TDM_ERROR_NONE;
1058
1059         return display_buffer;
1060 }
1061
1062 static int
1063 _sprd_drm_user_handler(struct drm_event *event)
1064 {
1065         RETURN_VAL_IF_FAIL(event, -1);
1066
1067         TDM_DBG("got event %d\n", event->type);
1068
1069         if (event->type != DRM_SPRD_IPP_EVENT)
1070                 return -1;
1071         tdm_sprd_pp_handler((struct drm_sprd_ipp_event *) event);
1072
1073         return 0;
1074 }
1075
1076 static void
1077 _sprd_drm_vblank_event(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1078 {
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;
1082
1083         if (!vblank_data) {
1084                 TDM_ERR("no vblank data");
1085                 return;
1086         }
1087
1088         output_data = vblank_data->output_data;
1089         if (!output_data) {
1090                 TDM_ERR("no output data");
1091                 return;
1092         }
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);
1097                 break;
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;
1103                         }
1104                 }
1105
1106                 if (output_data->commit_func)
1107                         output_data->commit_func(output_data, sequence, tv_sec, tv_usec, vblank_data->user_data);
1108
1109                 break;
1110         default:
1111                 break;
1112         }
1113         free(vblank_data);
1114 }
1115
1116 static void
1117 _sprd_drm_flip_complete_event(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
1118 {
1119         TDM_DBG("FLIP EVENT");
1120 }
1121
1122 #if 0
1123 static int
1124 _sprd_layer_is_supported_format(tdm_sprd_layer_data *layer_data, tbm_format format)
1125 {
1126         RETURN_VAL_IF_FAIL(layer_data, 0);
1127         return IS_RGB(format);
1128 }
1129
1130 static int
1131 _sprd_hwc_window_is_reserved_buffer(tdm_sprd_hwc_window_data *hwc_window_data) {
1132         tbm_bo bo = NULL;
1133         int falgs = 0;
1134
1135         RETURN_VAL_IF_FAIL(hwc_window_data != NULL, 0);
1136         RETURN_VAL_IF_FAIL(hwc_window_data->display_buffer != NULL, 0);
1137
1138         bo = tbm_surface_internal_get_bo(hwc_window_data->display_buffer->buffer, 0);
1139         RETURN_VAL_IF_FAIL(bo != NULL, 0);
1140
1141         falgs = tbm_bo_get_flags(bo);
1142
1143         return falgs & TBM_BO_SCANOUT;
1144 }
1145 #endif
1146
1147 int
1148 _sprd_output_get_changed_number(tdm_sprd_hwc_data *hwc_data)
1149 {
1150         int num = 0;
1151         tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1152
1153         LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
1154                 if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
1155                         continue;
1156
1157                 if (hwc_window_data->client_type != hwc_window_data->validated_type)
1158                         num++;
1159         }
1160
1161         return num;
1162 }
1163
1164 static tdm_hwc_window *
1165 _sprd_hwc_create_window(tdm_sprd_hwc_data *hwc_data, tdm_hwc_window_info *info, tdm_error *error)
1166 {
1167         tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1168
1169         if (error)
1170                 *error = TDM_ERROR_NONE;
1171
1172         hwc_window_data = calloc(1, sizeof(tdm_sprd_hwc_window_data));
1173         if (!hwc_window_data) {
1174                 TDM_ERR("alloc failed");
1175                 if (error)
1176                         *error = TDM_ERROR_OUT_OF_MEMORY;
1177                 return NULL;
1178         }
1179
1180         hwc_window_data->hwc_data = hwc_data;
1181
1182         if (info)
1183                 memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
1184
1185         LIST_INITHEAD(&hwc_window_data->link);
1186
1187         return hwc_window_data;
1188 }
1189
1190 void
1191 tdm_sprd_display_destroy_output_list(tdm_sprd_data *sprd_data)
1192 {
1193         tdm_sprd_output_data *o = NULL, *oo = NULL;
1194
1195         if (LIST_IS_EMPTY(&sprd_data->output_list))
1196                 return;
1197
1198         LIST_FOR_EACH_ENTRY_SAFE(o, oo, &sprd_data->output_list, link) {
1199                 LIST_DEL(&o->link);
1200                 if (o->fb_fd > 0)
1201                         close(o->fb_fd);
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);
1206                         }
1207                 }
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) {
1211                                 LIST_DEL(&l->link);
1212                                 free(l);
1213                         }
1214                 }
1215                 free(o->output_modes);
1216                 free(o);
1217         }
1218 }
1219
1220 tdm_error
1221 tdm_sprd_display_create_output_list(tdm_sprd_data *sprd_data)
1222 {
1223         tdm_sprd_output_data *output_data = NULL;
1224
1225         RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&sprd_data->output_list), TDM_ERROR_OPERATION_FAILED);
1226
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;
1232
1233         TDM_DBG("output count: %d", sprd_data->output_count);
1234
1235         return TDM_ERROR_NONE;
1236 }
1237
1238 void
1239 tdm_sprd_display_destroy_buffer_list(tdm_sprd_data *sprd_data)
1240 {
1241         tdm_sprd_display_buffer *b = NULL, *bb = NULL;
1242
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);
1246         }
1247 }
1248
1249 tdm_error
1250 sprd_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
1251 {
1252         RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1253
1254         caps->max_layer_count = -1; /* not defined */
1255
1256         return TDM_ERROR_NONE;
1257 }
1258
1259 tdm_error
1260 sprd_display_get_pp_capability(tdm_backend_data *bdata, tdm_caps_pp *caps)
1261 {
1262         return tdm_sprd_pp_get_capability(bdata, caps);
1263 }
1264
1265 tdm_output **
1266 sprd_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
1267 {
1268         tdm_sprd_data *sprd_data = bdata;
1269         tdm_sprd_output_data *output_data = NULL;
1270         tdm_output **outputs;
1271         tdm_error ret;
1272         int i;
1273
1274         RETURN_VAL_IF_FAIL(sprd_data, NULL);
1275         RETURN_VAL_IF_FAIL(count, NULL);
1276
1277         *count = 0;
1278         LIST_FOR_EACH_ENTRY(output_data, &sprd_data->output_list, link)
1279                 (*count)++;
1280
1281         if (*count == 0) {
1282                 ret = TDM_ERROR_NONE;
1283                 goto failed_get;
1284         }
1285
1286         /* will be freed in frontend */
1287         outputs = calloc(*count, sizeof(tdm_sprd_output_data *));
1288         if (!outputs) {
1289                 TDM_ERR("failed: alloc memory");
1290                 *count = 0;
1291                 ret = TDM_ERROR_OUT_OF_MEMORY;
1292                 goto failed_get;
1293         }
1294
1295         i = 0;
1296         LIST_FOR_EACH_ENTRY(output_data, &sprd_data->output_list, link)
1297                 outputs[i++] = output_data;
1298
1299         if (error)
1300                 *error = TDM_ERROR_NONE;
1301
1302         return outputs;
1303 failed_get:
1304         if (error)
1305                 *error = ret;
1306         return NULL;
1307 }
1308
1309 tdm_error
1310 sprd_display_get_fd(tdm_backend_data *bdata, int *fd)
1311 {
1312         tdm_sprd_data *sprd_data = bdata;
1313
1314         RETURN_VAL_IF_FAIL(sprd_data, TDM_ERROR_INVALID_PARAMETER);
1315         RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
1316
1317         *fd = sprd_data->drm_fd;
1318
1319         return TDM_ERROR_NONE;
1320 }
1321
1322 tdm_error
1323 sprd_display_handle_events(tdm_backend_data *bdata)
1324 {
1325         tdm_sprd_data *sprd_data = bdata;
1326         RETURN_VAL_IF_FAIL(sprd_data, TDM_ERROR_INVALID_PARAMETER);
1327
1328         if (drmHandleEvent(sprd_data->drm_fd, &sprd_data->evctx) < 0)
1329                 return TDM_ERROR_OPERATION_FAILED;
1330
1331         return TDM_ERROR_NONE;
1332 }
1333
1334 tdm_pp *
1335 sprd_display_create_pp(tdm_backend_data *bdata, tdm_error *error)
1336 {
1337         tdm_sprd_data *sprd_data = bdata;
1338
1339         RETURN_VAL_IF_FAIL(sprd_data, NULL);
1340
1341         return tdm_sprd_pp_create(sprd_data, error);
1342 }
1343
1344 tdm_error
1345 sprd_output_get_capability(tdm_output *output, tdm_caps_output *caps)
1346 {
1347         tdm_sprd_output_data *output_data = output;
1348         int i;
1349         tdm_error ret;
1350
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);
1354
1355         memset(caps, 0, sizeof(tdm_caps_output));
1356
1357         snprintf(caps->maker, TDM_NAME_LEN, "unknown");
1358         snprintf(caps->model, TDM_NAME_LEN, "unknown");
1359         snprintf(caps->name, TDM_NAME_LEN, "unknown");
1360
1361         caps->status = output_data->status;
1362         caps->type = output_data->connector_type;
1363         caps->type_id = output_data->connector_type_id;
1364
1365         caps->mode_count = output_data->count_modes;
1366         caps->modes = calloc(1, sizeof(tdm_output_mode) * caps->mode_count);
1367         if (!caps->modes) {
1368                 ret = TDM_ERROR_OUT_OF_MEMORY;
1369                 TDM_ERR("alloc failed\n");
1370                 memset(caps, 0, sizeof(tdm_caps_output));
1371                 return ret;
1372         }
1373         for (i = 0; i < caps->mode_count; i++)
1374                 caps->modes[i] = output_data->output_modes[i];
1375
1376         caps->mmWidth = output_data->mi.width;
1377         caps->mmHeight = output_data->mi.height;
1378         caps->subpixel = 0;
1379
1380         caps->min_w = 0;
1381         caps->min_h = 0;
1382         caps->max_w = output_data->mi.xres_virtual;
1383         caps->max_h = output_data->mi.yres_virtual;
1384         caps->preferred_align = -1;
1385
1386         caps->prop_count = 0;
1387         caps->props = NULL;
1388
1389         if (output_data->sprd_data->hwc_mode)
1390                 caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
1391
1392         return TDM_ERROR_NONE;
1393 }
1394
1395 tdm_layer **
1396 sprd_output_get_layers(tdm_output *output, int *count, tdm_error *error)
1397 {
1398         tdm_sprd_output_data *output_data = output;
1399         tdm_sprd_layer_data *layer_data = NULL;
1400         tdm_layer **layers;
1401         tdm_error ret = TDM_ERROR_OPERATION_FAILED;
1402         int i;
1403
1404         RETURN_VAL_IF_FAIL(output_data, NULL);
1405         RETURN_VAL_IF_FAIL(count, NULL);
1406
1407         if (output_data->sprd_data->hwc_mode) {
1408                 TDM_INFO("layers aren't supported in HWC mode");
1409                 *count = 0;
1410                 ret = TDM_ERROR_NONE;
1411                 goto failed_get;
1412         }
1413
1414         *count = 0;
1415         LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1416                 (*count)++;
1417
1418         if (*count == 0) {
1419                 ret = TDM_ERROR_NONE;
1420                 goto failed_get;
1421         }
1422
1423         /* will be freed in frontend */
1424         layers = calloc(*count, sizeof(tdm_sprd_layer_data *));
1425         if (!layers) {
1426                 TDM_ERR("failed: alloc memory");
1427                 *count = 0;
1428                 ret = TDM_ERROR_OUT_OF_MEMORY;
1429                 goto failed_get;
1430         }
1431
1432         i = 0;
1433         LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
1434                 layers[i++] = layer_data;
1435
1436         if (error)
1437                 *error = TDM_ERROR_NONE;
1438
1439         return layers;
1440 failed_get:
1441         if (error)
1442                 *error = ret;
1443         return NULL;
1444 }
1445
1446 tdm_error
1447 sprd_output_set_property(tdm_output *output, unsigned int id, tdm_value value)
1448 {
1449         return TDM_ERROR_NOT_IMPLEMENTED;
1450 }
1451
1452 tdm_error
1453 sprd_output_get_property(tdm_output *output, unsigned int id, tdm_value *value)
1454 {
1455         return TDM_ERROR_NOT_IMPLEMENTED;
1456 }
1457
1458 tdm_error
1459 sprd_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data)
1460 {
1461         tdm_sprd_output_data *output_data = output;
1462         tdm_sprd_data *sprd_data;
1463         tdm_sprd_vblank_data *vblank_data;
1464         uint target_msc;
1465         tdm_error ret;
1466
1467         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1468
1469         vblank_data = calloc(1, sizeof(tdm_sprd_vblank_data));
1470         if (!vblank_data) {
1471                 TDM_ERR("alloc failed");
1472                 return TDM_ERROR_OUT_OF_MEMORY;
1473         }
1474
1475         sprd_data = output_data->sprd_data;
1476
1477         ret = _tdm_sprd_display_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
1478         if (ret != TDM_ERROR_NONE)
1479                 goto failed_vblank;
1480
1481         target_msc += interval;
1482
1483         vblank_data->type = VBLANK_TYPE_WAIT;
1484         vblank_data->output_data = output_data;
1485         vblank_data->user_data = user_data;
1486
1487         ret = _tdm_sprd_display_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
1488         if (ret != TDM_ERROR_NONE)
1489                 goto failed_vblank;
1490
1491         return TDM_ERROR_NONE;
1492 failed_vblank:
1493         free(vblank_data);
1494         return ret;
1495 }
1496
1497 tdm_error
1498 sprd_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func)
1499 {
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;
1504
1505         return TDM_ERROR_NONE;
1506 }
1507
1508 tdm_error
1509 sprd_output_commit(tdm_output *output, int sync, void *user_data)
1510 {
1511         tdm_sprd_output_data *output_data = output;
1512         tdm_sprd_data *sprd_data;
1513         tdm_error ret = TDM_ERROR_NONE;
1514
1515         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1516
1517         sprd_data = output_data->sprd_data;
1518
1519         _tdm_sprd_display_do_commit(output_data);
1520         RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
1521
1522         tdm_sprd_vblank_data *vblank_data = calloc(1, sizeof(tdm_sprd_vblank_data));
1523         uint target_msc;
1524
1525         if (!vblank_data) {
1526                 TDM_ERR("alloc failed");
1527                 return TDM_ERROR_OUT_OF_MEMORY;
1528         }
1529
1530         ret = _tdm_sprd_display_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
1531         if (ret != TDM_ERROR_NONE) {
1532                 free(vblank_data);
1533                 return ret;
1534         }
1535
1536         target_msc++;
1537
1538         vblank_data->type = VBLANK_TYPE_COMMIT;
1539         vblank_data->output_data = output_data;
1540         vblank_data->user_data = user_data;
1541
1542         ret = _tdm_sprd_display_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
1543         if (ret != TDM_ERROR_NONE) {
1544                 free(vblank_data);
1545                 return ret;
1546         }
1547
1548         return TDM_ERROR_NONE;
1549 }
1550
1551 tdm_error
1552 sprd_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func)
1553 {
1554         tdm_sprd_output_data *output_data = output;
1555
1556         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1557         RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
1558
1559         output_data->commit_func = func;
1560
1561         return TDM_ERROR_NONE;
1562 }
1563
1564 tdm_error
1565 sprd_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
1566 {
1567         tdm_sprd_output_data *output_data = output;
1568         tdm_error ret;
1569
1570         if (output_data->dpms_value == dpms_value)
1571                 return TDM_ERROR_NONE;
1572
1573         output_data->dpms_value = dpms_value;
1574
1575         if (dpms_value != TDM_OUTPUT_DPMS_ON)
1576                 ret = _tdm_sprd_display_output_disable(output_data);
1577         else
1578                 ret = _tdm_sprd_display_output_enable(output_data);
1579
1580         return ret;
1581 }
1582
1583 tdm_error
1584 sprd_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
1585 {
1586         RETURN_VAL_IF_FAIL(output, TDM_ERROR_INVALID_PARAMETER);
1587         RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
1588
1589         tdm_sprd_output_data *output_data = output;
1590
1591         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1592
1593         *dpms_value = output_data->dpms_value;
1594
1595         return TDM_ERROR_NONE;
1596 }
1597
1598 tdm_error
1599 sprd_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
1600 {
1601         tdm_sprd_output_data *output_data = output;
1602         tdm_error ret = TDM_ERROR_NONE;
1603
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);
1607
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);
1613                         return ret;
1614                 }
1615         }
1616
1617         output_data->current_mode = mode;
1618         output_data->mode_changed = 1;
1619
1620         return TDM_ERROR_NONE;
1621 }
1622
1623 tdm_error
1624 sprd_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
1625 {
1626         tdm_sprd_output_data *output_data = output;
1627
1628         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
1629         RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
1630
1631         *mode = output_data->current_mode;
1632
1633         return TDM_ERROR_NONE;
1634 }
1635
1636 tdm_error
1637 sprd_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
1638 {
1639         tdm_sprd_layer_data *layer_data = layer;
1640         int i;
1641         tdm_error ret;
1642
1643         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1644         RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
1645
1646         memset(caps, 0, sizeof(tdm_caps_layer));
1647
1648         caps->capabilities = layer_data->capabilities;
1649         caps->zpos = layer_data->zpos;
1650
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));
1657                 return ret;
1658         }
1659
1660         for (i = 0; i < caps->format_count; i++)
1661                 caps->formats[i] = layer_data->formats[i];
1662
1663         caps->prop_count = 0;
1664         caps->props = NULL;
1665
1666         return TDM_ERROR_NONE;
1667 }
1668
1669 tdm_error
1670 sprd_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value)
1671 {
1672         return TDM_ERROR_NOT_IMPLEMENTED;
1673 }
1674
1675 tdm_error
1676 sprd_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value)
1677 {
1678         return TDM_ERROR_NOT_IMPLEMENTED;
1679 }
1680
1681 tdm_error
1682 sprd_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
1683 {
1684         tdm_sprd_layer_data *layer_data = layer;
1685
1686         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1687         RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1688
1689         layer_data->info = *info;
1690         layer_data->info_changed = 1;
1691
1692         return TDM_ERROR_NONE;
1693 }
1694
1695 tdm_error
1696 sprd_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
1697 {
1698         tdm_sprd_layer_data *layer_data = layer;
1699
1700         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1701         RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
1702
1703         *info = layer_data->info;
1704
1705         return TDM_ERROR_NONE;
1706 }
1707
1708 tdm_error
1709 sprd_layer_set_buffer(tdm_layer *layer, tbm_surface_h surface)
1710 {
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;
1715
1716         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1717         RETURN_VAL_IF_FAIL(surface, TDM_ERROR_INVALID_PARAMETER);
1718
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);
1725         }
1726
1727         layer_data->display_buffer = display_buffer;
1728         layer_data->display_buffer_changed = 1;
1729
1730         return TDM_ERROR_NONE;
1731
1732 }
1733
1734 tdm_error
1735 sprd_layer_unset_buffer(tdm_layer *layer)
1736 {
1737         tdm_sprd_layer_data *layer_data = layer;
1738         tdm_sprd_data *sprd_data;
1739
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);
1743
1744         sprd_data = layer_data->output_data->sprd_data;
1745
1746         if (sprd_data->hwc_mode) {
1747                 if (layer_data->display_buffer)
1748                         layer_data->display_buffer_changed = 1;
1749         } else
1750                 _tdm_sprd_display_layer_disable(layer);
1751         layer_data->display_buffer = NULL;
1752
1753         return TDM_ERROR_NONE;
1754 }
1755
1756 tdm_error
1757 sprd_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags)
1758 {
1759         tdm_sprd_layer_data *layer_data = layer;
1760
1761         switch (layer_data->zpos) {
1762         case 0:
1763         case 1:
1764                 *flags = TBM_BO_SCANOUT;
1765                 break;
1766         default:
1767                 return TDM_ERROR_INVALID_PARAMETER;
1768         }
1769
1770         return TDM_ERROR_NONE;
1771 }
1772
1773 tdm_error
1774 tdm_sprd_display_init_event_handling(tdm_sprd_data *sprd_data)
1775 {
1776         RETURN_VAL_IF_FAIL(sprd_data, TDM_ERROR_INVALID_PARAMETER);
1777
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;
1781
1782         drmAddUserHandler(sprd_data->drm_fd, _sprd_drm_user_handler);
1783
1784         return TDM_ERROR_NONE;
1785 }
1786
1787 void
1788 tdm_sprd_display_deinit_event_handling(tdm_sprd_data *sprd_data)
1789 {
1790         RETURN_VOID_IF_FAIL(sprd_data);
1791
1792         drmRemoveUserHandler(sprd_data->drm_fd, _sprd_drm_user_handler);
1793 }
1794
1795 tdm_backend_data*
1796 sprd_output_get_sprd_data(tdm_output *output)
1797 {
1798         RETURN_VAL_IF_FAIL(output, NULL);
1799         tdm_sprd_output_data *output_data = output;
1800         return output_data->sprd_data;
1801 }
1802
1803 tdm_error
1804 sprd_output_attach_capture(tdm_output *output, tdm_capture *capture)
1805 {
1806         RETURN_VAL_IF_FAIL(output, TDM_ERROR_INVALID_PARAMETER);
1807         RETURN_VAL_IF_FAIL(capture, TDM_ERROR_INVALID_PARAMETER);
1808
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;
1817 }
1818
1819 void
1820 sprd_output_dettach_capture(tdm_output *output, tdm_capture *capture)
1821 {
1822         RETURN_VOID_IF_FAIL(output);
1823         RETURN_VOID_IF_FAIL(capture);
1824
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) {
1830                                 LIST_DEL(&l->link);
1831                                 free(l);
1832                         }
1833                 }
1834         }
1835 }
1836
1837 tdm_error
1838 sprd_layer_get_buffer(tdm_layer *layer, tbm_surface_h *surface)
1839 {
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) {
1843                 if (surface) {
1844                         *surface = NULL;
1845                 }
1846                 return TDM_ERROR_NONE;
1847         }
1848         if (surface) {
1849                 *surface = layer_data->display_buffer->buffer;
1850         }
1851         return  TDM_ERROR_NONE;
1852 }
1853
1854 tdm_error
1855 sprd_layer_get_zpos(tdm_layer *layer, int *zpos)
1856 {
1857         tdm_sprd_layer_data *layer_data = layer;
1858         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
1859         if (zpos) {
1860                 *zpos = layer_data->zpos;
1861         }
1862         return TDM_ERROR_NONE;
1863 }
1864
1865 tdm_hwc_window *
1866 sprd_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
1867 {
1868         tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1869         tdm_sprd_hwc_data *hwc_data = hwc;
1870
1871         RETURN_VAL_IF_FAIL(hwc_data, NULL);
1872
1873         hwc_window_data = _sprd_hwc_create_window(hwc_data, NULL, error);
1874         RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
1875
1876         LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
1877
1878         TDM_DBG("hwc_window(%p) create", hwc_window_data);
1879         if (error)
1880                 *error = TDM_ERROR_NONE;
1881
1882         return hwc_window_data;
1883 }
1884
1885 void
1886 sprd_hwc_window_destroy(tdm_hwc_window *hwc_window)
1887 {
1888         tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
1889
1890         if (!hwc_window_data)
1891                 return;
1892
1893         LIST_DEL(&hwc_window_data->link);
1894
1895         free(hwc_window_data);
1896 }
1897
1898 tdm_error
1899 sprd_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
1900 {
1901         tdm_sprd_hwc_data *hwc_data = hwc;
1902         tdm_sprd_hwc_window_data *hwc_window_data = NULL;
1903
1904         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
1905         RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
1906
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;
1913                         continue;
1914                   }
1915
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;
1919                 }
1920         }
1921
1922     /* debugging log */
1923         LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
1924                 if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
1925                         continue;
1926
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));
1930         }
1931
1932     /* The driver always needs the target_buffer */
1933         hwc_data->need_target_window = 1;
1934
1935         *num_types = _sprd_output_get_changed_number(hwc_data);
1936         if (*num_types == 0)
1937                 hwc_data->need_validate = 0;
1938
1939         return TDM_ERROR_NONE;
1940 }
1941
1942 tdm_error
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)
1945 {
1946         tdm_sprd_hwc_data *hwc_data = hwc;
1947         int num = 0;
1948
1949         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
1950         RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
1951
1952         if ((hwc_window == NULL) || (composition_types == NULL)) {
1953                 *num_elements = _sprd_output_get_changed_number(hwc_data);
1954                 return TDM_ERROR_NONE;
1955         }
1956
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)
1960                         continue;
1961
1962                 if (num >= *num_elements)
1963                         break;
1964
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;
1968                         num++;
1969                 }
1970         }
1971
1972         /* set real num of changed composition types */
1973         *num_elements = num;
1974
1975         return TDM_ERROR_NONE;
1976 }
1977
1978 tdm_error
1979 sprd_hwc_accept_changes(tdm_hwc *hwc)
1980 {
1981         tdm_sprd_hwc_data *hwc_data = hwc;
1982
1983         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
1984
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)
1988                         continue;
1989
1990                 hwc_window_data->client_type = hwc_window_data->validated_type;
1991         }
1992
1993         hwc_data->need_validate = 0;
1994
1995         return TDM_ERROR_NONE;
1996 }
1997
1998 tbm_surface_queue_h
1999 sprd_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
2000 {
2001         tdm_sprd_hwc_data *hwc_data = hwc;
2002         tbm_surface_queue_h tqueue = NULL;
2003
2004         if (error)
2005                 *error = TDM_ERROR_INVALID_PARAMETER;
2006
2007         RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
2008
2009         if (hwc_data->target_hwc_window == NULL) {
2010                 if (error)
2011                         *error = TDM_ERROR_OPERATION_FAILED;
2012                 return NULL;
2013         }
2014
2015         tqueue = _sprd_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
2016         RETURN_VAL_IF_FAIL(tqueue, NULL);
2017
2018         if (error)
2019                 *error = TDM_ERROR_NONE;
2020         return tqueue;
2021 }
2022
2023 tdm_error
2024 sprd_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
2025 {
2026         tdm_sprd_hwc_data *hwc_data = hwc;
2027         tdm_error err;
2028
2029         /* TODO: as the sprd-driver currently doesn't support DEVICE to CLIENT transition.
2030          * we silence skip 'composited_wnds' */
2031
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);
2034
2035         err = sprd_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
2036         RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
2037
2038         err = sprd_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
2039         RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
2040
2041         return TDM_ERROR_NONE;
2042 }
2043
2044 tdm_error
2045 sprd_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
2046 {
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);
2050
2051         // TODO: fix these formats.
2052         *formats = hwc_window_video_formats;
2053         *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
2054
2055         return TDM_ERROR_NONE;
2056 }
2057
2058 tdm_error
2059 sprd_hwc_get_video_capability(tdm_hwc *hwc, tdm_hwc_video_capability *video_capability)
2060 {
2061         RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
2062         RETURN_VAL_IF_FAIL(video_capability != NULL, TDM_ERROR_INVALID_PARAMETER);
2063
2064         *video_capability = TDM_HWC_VIDEO_CAPABILITY_SCANOUT;
2065
2066         return TDM_ERROR_NONE;
2067 }
2068
2069 tdm_error
2070 sprd_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
2071 {
2072         tdm_sprd_hwc_data *hwc_data = hwc;
2073
2074         RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2075
2076         // TODO:
2077
2078         return TDM_ERROR_NONE;
2079 }
2080
2081 tdm_error
2082 sprd_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
2083                                                                         tdm_hwc_window_composition comp_type)
2084 {
2085         tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2086         tdm_sprd_hwc_data *hwc_data = hwc_window_data->hwc_data;
2087
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);
2090
2091         if (hwc_window_data->client_type == comp_type)
2092                 return TDM_ERROR_NONE;
2093
2094         hwc_window_data->client_type = comp_type;
2095
2096         hwc_data->need_validate = 1;
2097
2098         return TDM_ERROR_NONE;
2099
2100 }
2101
2102 tdm_error
2103 sprd_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage)
2104 {
2105         tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2106
2107         RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2108
2109         //TODO::
2110
2111         return TDM_ERROR_NONE;
2112 }
2113
2114 tdm_error
2115 sprd_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
2116 {
2117         tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2118         tdm_sprd_hwc_data *hwc_data = hwc_window_data->hwc_data;
2119
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);
2123
2124         if (memcmp(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info)) == 0)
2125                 return TDM_ERROR_NONE;
2126
2127         hwc_window_data->info = *info;
2128         hwc_data->need_validate = 1;
2129
2130         return TDM_ERROR_NONE;
2131 }
2132
2133 tdm_error
2134 sprd_hwc_window_get_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
2135 {
2136         tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2137
2138         RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2139         RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
2140
2141         *info = hwc_window_data->info;
2142
2143         return TDM_ERROR_NONE;
2144 }
2145
2146 tdm_error
2147 sprd_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
2148 {
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;
2154
2155         tdm_sprd_display_buffer *display_buffer = NULL;
2156
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);
2164
2165         if (!surface) {
2166                 hwc_window_data->display_buffer = NULL;
2167                 return TDM_ERROR_NONE;
2168         }
2169
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);
2175         }
2176
2177         if (hwc_window_data->display_buffer == display_buffer)
2178                 return TDM_ERROR_NONE;
2179
2180         hwc_window_data->display_buffer = display_buffer;
2181
2182         return TDM_ERROR_NONE;
2183 }
2184
2185 tdm_error
2186 sprd_hwc_initailize_target_window(tdm_hwc *hwc, int width, int height)
2187 {
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;
2192
2193         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
2194
2195         info.dst_pos.x = 0;
2196         info.dst_pos.y = 0;
2197         info.dst_pos.h = height;
2198         info.dst_pos.w = width;
2199
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;
2204
2205         info.src_config.size.h = width;
2206         info.src_config.size.v = height;
2207         info.src_config.format = TBM_FORMAT_ARGB8888;
2208
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;
2213         }
2214
2215         if (hwc_data->target_hwc_window)
2216                 sprd_hwc_window_destroy(hwc_data->target_hwc_window);
2217
2218         hwc_data->target_hwc_window = target_hwc_window;
2219         hwc_data->need_set_crtc = 1;
2220
2221         return TDM_ERROR_NONE;
2222 }
2223
2224 tdm_hwc *
2225 sprd_output_get_hwc(tdm_output *output, tdm_error *error)
2226 {
2227         tdm_sprd_hwc_data *hwc_data = NULL;
2228         tdm_sprd_output_data *output_data = output;
2229
2230         if (!output_data) {
2231                 TDM_ERR("invalid params");
2232                 if (error)
2233                         *error = TDM_ERROR_INVALID_PARAMETER;
2234                 return NULL;
2235         }
2236
2237         if (output_data->hwc_data) {
2238                 TDM_INFO("hwc_data already exists");
2239                 if (error)
2240                         *error = TDM_ERROR_NONE;
2241                 return output_data->hwc_data;
2242         }
2243
2244         hwc_data = calloc(1, sizeof(tdm_sprd_hwc_data));
2245         if (!hwc_data) {
2246                 TDM_ERR("alloc failed");
2247                 if (error)
2248                         *error = TDM_ERROR_OUT_OF_MEMORY;
2249                 return NULL;
2250         }
2251         hwc_data->output_data = output_data;
2252
2253         LIST_INITHEAD(&hwc_data->hwc_window_list);
2254
2255         output_data->hwc_data = hwc_data;
2256
2257         if (error)
2258                 *error = TDM_ERROR_NONE;
2259
2260         return hwc_data;
2261 }
2262
2263 tdm_error
2264 sprd_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
2265 {
2266 // TODO:
2267
2268         return TDM_ERROR_NONE;
2269 }
2270
2271 tdm_error
2272 sprd_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
2273 {
2274         tdm_sprd_hwc_data *hwc_data = hwc;
2275
2276         RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
2277         RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
2278
2279         hwc_data->commit_func = func;
2280
2281         return TDM_ERROR_NONE;
2282 }
2283
2284 tdm_error
2285 sprd_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value)
2286 {
2287         tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2288
2289         RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2290
2291         //TODO:
2292
2293         return TDM_ERROR_NONE;
2294 }
2295
2296 tdm_error
2297 sprd_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value)
2298 {
2299         tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
2300
2301         RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
2302
2303         //TODO:
2304
2305         return TDM_ERROR_NONE;
2306 }