capture: Fix NULL pointer dereference
[platform/adaptation/spreadtrum/libtdm-sprd.git] / src / libhal-backend-tdm-sprd / tdm_sprd_capture.c
1 /**************************************************************************
2
3 libtdm_sprd
4
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "tdm_backend_sprd.h"
36
37 #define NUM_LAYERS  2
38
39 typedef struct _tdm_sprd_capture_buffer {
40         tbm_surface_h buffer;
41         struct list_head link;
42 } tdm_sprd_capture_buffer;
43
44 typedef struct _tdm_sprd_capture_pp_data {
45         hal_tdm_pp * pp_link;
46         tbm_surface_h src_buffer;
47         tbm_surface_h dst_buffer;
48         struct list_head link;
49 } tdm_sprd_capture_pp_data;
50
51 typedef struct _tdm_sprd_capture_composite_data {
52         tbm_surface_h temp_layer_buffer[LAYER_COUNT_PER_OUTPUT];
53         hal_tdm_pos dst_pos[LAYER_COUNT_PER_OUTPUT];
54         int zpos[LAYER_COUNT_PER_OUTPUT];
55         tbm_surface_h client_buffer;
56         tbm_surface_h temp_composite_buffer;
57         tdm_sprd_capture_pp_data * composite_buf_pp_task;
58         int current_done_buf_num;
59         int need_done_buf_num;
60         struct list_head link;
61 } tdm_sprd_capture_composite;
62
63 typedef struct _tdm_sprd_capture_data {
64         int stamp;
65         int removing;
66         tdm_sprd_display *display_data;
67
68         hal_tdm_output *output_data;
69
70         hal_tdm_info_capture info;
71         int info_changed;
72         struct list_head pending_buffer_list;
73         struct list_head pp_convert_list;
74         struct list_head composite_list;
75
76         hal_tdm_capture_done_handler done_func;
77         void *done_user_data;
78         struct list_head link;
79 } tdm_sprd_capture_data;
80
81 typedef struct _tdm_sprd_capture_internal {
82         tdm_sprd_capture_data *stream_data;
83         int timer_fd;
84         int removing;
85         int timer_running;
86 } tdm_sprd_capture_internal;
87
88 static tdm_sprd_capture_internal *g_capture_data;
89
90 static tbm_format capture_client_formats[] = {
91         TBM_FORMAT_XRGB8888,
92         TBM_FORMAT_ARGB8888,
93         TBM_FORMAT_NV12,
94         TBM_FORMAT_YUV420
95 };
96
97 #define NUM_CAPTURE_FORMAT   (sizeof(capture_client_formats) / sizeof(capture_client_formats[0]))
98
99 static int capture_list_init;
100 static struct list_head capture_list;
101 static int capture_stamp = 1001;
102
103 int _tdm_sprd_capture_check_struct(tdm_sprd_capture_data *capture_data)
104 {
105         TDM_BACKEND_RETURN_VAL_IF_FAIL(capture_list_init == 1, 0);
106         if (capture_data == NULL) {
107                 TDM_BACKEND_WRN("capture nil(0). Received NULL pointer");
108                 return 0;
109         }
110         tdm_sprd_capture_data * capture_next = NULL;
111         LIST_FOR_EACH_ENTRY(capture_next, &capture_list, link) {
112                 if (capture_next->stamp == capture_data->stamp)
113                         return 1;
114         }
115         TDM_BACKEND_INFO("capture %p(%d). Maybe, receive handler after remove",
116                         capture_data, capture_data->stamp);
117         return 0;
118 }
119
120 static void
121 _tdm_sprd_capture_oneshot_center_rect(int src_w, int src_h, int dst_w, int dst_h, hal_tdm_pos *fit)
122 {
123         float rw = (float)src_w / dst_w;
124         float rh = (float)src_h / dst_h;
125
126         fit->x = fit->y = 0;
127
128         if (rw > rh) {
129                 fit->w = dst_w;
130                 fit->h = src_h / rw;
131                 fit->y = (dst_h - fit->h) / 2;
132         } else if (rw < rh) {
133                 fit->w = src_w / rh;
134                 fit->h = dst_h;
135                 fit->x = (dst_w - fit->w) / 2;
136         } else {
137                 fit->w = dst_w;
138                 fit->h = dst_h;
139         }
140
141         fit->x = fit->x & ~0x1;
142 }
143
144 static void
145 _tdm_sprd_capture_oneshot_rect_scale(int src_w, int src_h, int dst_w, int dst_h, hal_tdm_pos *scale)
146 {
147         float ratio;
148         hal_tdm_pos center = {0,};
149
150         _tdm_sprd_capture_oneshot_center_rect(src_w, src_h, dst_w, dst_h, &center);
151
152         ratio = (float)center.w / src_w;
153         scale->x = scale->x * ratio + center.x;
154         scale->y = scale->y * ratio + center.y;
155         scale->w = scale->w * ratio;
156         scale->h = scale->h * ratio;
157 }
158
159 static void
160 _tdm_sprd_capture_destroy_converter(tdm_sprd_capture_pp_data ** pp_task_p)
161 {
162         TDM_BACKEND_RETURN_IF_FAIL(pp_task_p);
163         TDM_BACKEND_RETURN_IF_FAIL(*pp_task_p);
164         LIST_DEL(&(*pp_task_p)->link);
165         if ((*pp_task_p)->pp_link)
166                 sprd_pp_destroy((*pp_task_p)->pp_link);
167         if ((*pp_task_p)->src_buffer) {
168                 tbm_surface_internal_unref((*pp_task_p)->src_buffer);
169                 (*pp_task_p)->src_buffer = NULL;
170         }
171         if ((*pp_task_p)->dst_buffer) {
172                 tbm_surface_internal_unref((*pp_task_p)->dst_buffer);
173                 (*pp_task_p)->dst_buffer = NULL;
174         }
175         free(*pp_task_p);
176         *pp_task_p = NULL;
177 }
178
179 static pixman_format_code_t
180 _tdm_sprd_pixman_format_get(tbm_format format)
181 {
182         switch (format) {
183         case TBM_FORMAT_ARGB8888:
184                 return PIXMAN_a8r8g8b8;
185         case TBM_FORMAT_XRGB8888:
186                 return PIXMAN_x8r8g8b8;
187         default:
188                 return 0;
189         }
190
191         return 0;
192 }
193
194 static hal_tdm_error
195 _tdm_sprd_capture_convert_buffer(tbm_surface_h srcbuf, tbm_surface_h dstbuf,
196                                                   hal_tdm_pos *srcpos, hal_tdm_pos *dstpos,
197                                                   hal_tdm_transform transform, int over)
198 {
199         tbm_surface_info_s src_info, dst_info;
200         pixman_image_t *src_img = NULL, *dst_img = NULL;
201         pixman_format_code_t src_format, dst_format;
202         double scale_x, scale_y;
203         int rotate_step, bos;
204         pixman_transform_t t;
205         struct pixman_f_transform ft;
206         pixman_op_t op;
207         int src_stride, dst_stride;
208         int buf_width, err;
209         hal_tdm_error ret = HAL_TDM_ERROR_OPERATION_FAILED;
210
211         TDM_BACKEND_RETURN_VAL_IF_FAIL(srcbuf != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
212         TDM_BACKEND_RETURN_VAL_IF_FAIL(dstbuf != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
213
214         bos = tbm_surface_internal_get_num_bos(srcbuf);
215         TDM_BACKEND_RETURN_VAL_IF_FAIL(bos == 1, HAL_TDM_ERROR_OPERATION_FAILED);
216
217         bos = tbm_surface_internal_get_num_bos(dstbuf);
218         TDM_BACKEND_RETURN_VAL_IF_FAIL(bos == 1, HAL_TDM_ERROR_OPERATION_FAILED);
219
220         err = tbm_surface_map(srcbuf, TBM_OPTION_READ, &src_info);
221         TDM_BACKEND_RETURN_VAL_IF_FAIL(err == TBM_SURFACE_ERROR_NONE, HAL_TDM_ERROR_OPERATION_FAILED);
222
223         err = tbm_surface_map(dstbuf, TBM_OPTION_WRITE, &dst_info);
224         TDM_BACKEND_GOTO_VAL_IF_FAIL(err == TBM_SURFACE_ERROR_NONE, unmap_srcbuf);
225
226         /* not handle buffers which have 2 more gem handles */
227         TDM_BACKEND_GOTO_VAL_IF_FAIL(src_info.planes[0].ptr != NULL, unmap_dstbuf);
228         TDM_BACKEND_GOTO_VAL_IF_FAIL(dst_info.planes[0].ptr != NULL, unmap_dstbuf);
229
230         src_format = _tdm_sprd_pixman_format_get(src_info.format);
231         TDM_BACKEND_GOTO_VAL_IF_FAIL(src_format > 0, unmap_dstbuf);
232         dst_format = _tdm_sprd_pixman_format_get(dst_info.format);
233         TDM_BACKEND_GOTO_VAL_IF_FAIL(dst_format > 0, unmap_dstbuf);
234
235         buf_width = src_info.planes[0].stride >> 2;
236         src_stride = src_info.planes[0].stride;
237         src_img = pixman_image_create_bits(src_format, buf_width, src_info.height,
238                                                                            (uint32_t*)src_info.planes[0].ptr, src_stride);
239         TDM_BACKEND_GOTO_VAL_IF_FAIL(src_img, unref_img);
240
241         buf_width = dst_info.planes[0].stride >> 2;
242         dst_stride = dst_info.planes[0].stride;
243         dst_img = pixman_image_create_bits(dst_format, buf_width, dst_info.height,
244                                                                            (uint32_t*)dst_info.planes[0].ptr, dst_stride);
245         TDM_BACKEND_GOTO_VAL_IF_FAIL(dst_img, unref_img);
246
247         pixman_f_transform_init_identity(&ft);
248
249         if (transform & HAL_TDM_TRANSFORM_FLIPPED) {
250                 pixman_f_transform_scale(&ft, NULL, -1, 1);
251                 pixman_f_transform_translate(&ft, NULL, dstpos->w, 0);
252         }
253
254         rotate_step = transform & 0x3;
255         if (rotate_step > 0) {
256                 int c, s, tx = 0, ty = 0;
257                 switch (rotate_step) {
258                 case 1:
259                         c = 0, s = -1, tx = -dstpos->w;
260                         break;
261                 case 2:
262                         c = -1, s = 0, tx = -dstpos->w, ty = -dstpos->h;
263                         break;
264                 case 3:
265                         c = 0, s = 1, ty = -dstpos->h;
266                         break;
267                 }
268                 pixman_f_transform_translate(&ft, NULL, tx, ty);
269                 pixman_f_transform_rotate(&ft, NULL, c, s);
270         }
271
272         if (rotate_step % 2 == 0) {
273                 scale_x = (double)srcpos->w / dstpos->w;
274                 scale_y = (double)srcpos->h / dstpos->h;
275         } else {
276                 scale_x = (double)srcpos->w / dstpos->h;
277                 scale_y = (double)srcpos->h / dstpos->w;
278         }
279
280         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
281         pixman_f_transform_translate(&ft, NULL, srcpos->x, srcpos->y);
282         pixman_transform_from_pixman_f_transform(&t, &ft);
283         pixman_image_set_transform(src_img, &t);
284
285         op = (!over) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER;
286
287         pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0,
288                                                    dstpos->x, dstpos->y, dstpos->w, dstpos->h);
289
290         ret = HAL_TDM_ERROR_NONE;
291
292 unref_img:
293         if (src_img)
294                 pixman_image_unref(src_img);
295         if (dst_img)
296                 pixman_image_unref(dst_img);
297 unmap_dstbuf:
298         tbm_surface_unmap(dstbuf);
299 unmap_srcbuf:
300         tbm_surface_unmap(srcbuf);
301
302         return ret;
303 }
304
305 static hal_tdm_error
306 _tdm_sprd_capture_composite_sw(tdm_sprd_capture_data *capture_data,
307                                                            tdm_sprd_capture_composite * composite_data,
308                                                            tbm_surface_h composite_buf)
309 {
310         int i, k;
311         hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
312         tbm_surface_h temp_buffer = NULL;
313         int temp_zpos = 0;
314         hal_tdm_pos temp_dpos = {0, 0, 0, 0};
315 /* Good old bubble sort */
316         for (k = 0; k < LAYER_COUNT_PER_OUTPUT-1; ++k) {
317                 for (i = 0; i < LAYER_COUNT_PER_OUTPUT - 1 - k; ++i) {
318                         if (composite_data->zpos[i] > composite_data->zpos[i+1]) {
319                                 temp_buffer = composite_data->temp_layer_buffer[i];
320                                 temp_zpos = composite_data->zpos[i];
321                                 temp_dpos = composite_data->dst_pos[i];
322                                 composite_data->temp_layer_buffer[i] = composite_data->temp_layer_buffer[i+1];
323                                 composite_data->zpos[i] = composite_data->zpos[i+1];
324                                 composite_data->dst_pos[i] = composite_data->dst_pos[i+1];
325                                 composite_data->dst_pos[i+1] = temp_dpos;
326                                 composite_data->temp_layer_buffer[i+1] = temp_buffer;
327                                 composite_data->zpos[i+1] = temp_zpos;
328                         }
329                 }
330         }
331         for (i = 0; i < LAYER_COUNT_PER_OUTPUT; i++) {
332                 if (composite_data->temp_layer_buffer[i]) {
333                         hal_tdm_pos src_pos = {.x = 0,
334                                                            .y = 0,
335                                                            .w = tbm_surface_get_width(composite_data->temp_layer_buffer[i]),
336                                                            .h = tbm_surface_get_height(composite_data->temp_layer_buffer[i])};
337                         tdm_err = _tdm_sprd_capture_convert_buffer(composite_data->temp_layer_buffer[i],
338                                                                                                 composite_buf, &src_pos,
339                                                                                                 &composite_data->dst_pos[i], 0, 1);
340                         if (tdm_err != HAL_TDM_ERROR_NONE) {
341                                 TDM_BACKEND_WRN("Capture %p error %d Can't composite buffers src %p dst %p. Skip",
342                                                 capture_data,  tdm_err, composite_data->temp_layer_buffer[i], composite_buf);
343                         }
344                         tbm_surface_internal_unref(composite_data->temp_layer_buffer[i]);
345                         composite_data->temp_layer_buffer[i] = NULL;
346                 }
347         }
348
349         return HAL_TDM_ERROR_NONE;
350 }
351
352 static void
353 _tdm_sprd_capture_pp_done_handler (hal_tdm_pp *pp, tbm_surface_h src,
354                                                           tbm_surface_h dst, void *user_data)
355 {
356         if (!_tdm_sprd_capture_check_struct(user_data)) {
357                 return;
358         }
359         tdm_sprd_capture_data *capture_data = user_data;
360         if (capture_data->removing) {
361                 TDM_BACKEND_INFO("Capture removing. Skip handler");
362                 return;
363         }
364         tdm_sprd_capture_composite *composite_data = NULL, *composite_next = NULL;
365         tdm_sprd_capture_pp_data  *pp_task = NULL, *pp_tasks_next = NULL;
366         int i;
367         LIST_FOR_EACH_ENTRY_SAFE(pp_task, pp_tasks_next, &capture_data->pp_convert_list, link) {
368                 if (pp_task->pp_link == pp) {
369                         tbm_surface_internal_unref(pp_task->src_buffer);
370                         pp_task->src_buffer = NULL;
371                         tbm_surface_internal_unref(pp_task->dst_buffer);
372                         pp_task->dst_buffer = NULL;
373                         break;
374                 }
375         }
376         LIST_FOR_EACH_ENTRY_SAFE(composite_data, composite_next, &capture_data->composite_list, link) {
377                 if (composite_data->client_buffer && composite_data->client_buffer == dst) {
378                         LIST_DEL(&composite_data->link);
379                         tbm_surface_internal_unref(composite_data->client_buffer);
380                         tbm_surface_internal_unref(composite_data->temp_composite_buffer);
381                         composite_data->temp_composite_buffer = NULL;
382                         if (capture_data->done_func) {
383                                 capture_data->done_func(capture_data,
384                                                                         composite_data->client_buffer,
385                                                                         capture_data->done_user_data);
386                         }
387                         free(composite_data);
388                         break;
389                 }
390                 for (i = 0; i < LAYER_COUNT_PER_OUTPUT; i++) {
391                         if (composite_data->temp_layer_buffer[i] && composite_data->temp_layer_buffer[i] == dst) {
392                                 composite_data->current_done_buf_num++;
393                         }
394                 }
395                 if (composite_data->current_done_buf_num == composite_data->need_done_buf_num) {
396                         if (!composite_data->temp_composite_buffer) {
397                                 _tdm_sprd_capture_composite_sw(capture_data, composite_data,
398                                                                                            composite_data->client_buffer);
399                                 tbm_surface_internal_unref(composite_data->client_buffer);
400                                 if (capture_data->done_func) {
401                                         capture_data->done_func(capture_data,
402                                                                                 composite_data->client_buffer,
403                                                                                 capture_data->done_user_data);
404                                 }
405                                 LIST_DEL(&composite_data->link);
406                                 free(composite_data);
407                         } else {
408                                 _tdm_sprd_capture_composite_sw(capture_data, composite_data,
409                                                                                            composite_data->temp_composite_buffer);
410                                 sprd_pp_commit(composite_data->composite_buf_pp_task->pp_link);
411                                 composite_data->current_done_buf_num = 0;
412                         }
413                         break;
414                 }
415         }
416         TDM_BACKEND_DBG("capture pp handler done");
417 }
418
419 static hal_tdm_error
420 _tdm_sprd_capture_make_converter(tdm_sprd_capture_data *capture_data,
421                                                                  tbm_surface_h src, tbm_surface_h dst,
422                                                                  hal_tdm_pos *src_pos, hal_tdm_pos *dst_pos,
423                                                                  hal_tdm_transform transform,
424                                                                  tdm_sprd_capture_pp_data ** pp_task_p)
425 {
426         hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
427         hal_tdm_pp *pp = NULL;
428         hal_tdm_info_pp info_pp;
429         tdm_sprd_capture_pp_data  *new_pp_task = NULL, *pp_task = NULL, *pp_tasks_next = NULL;
430         tbm_format src_format, dst_format;
431         unsigned int src_bpp, src_stride, dst_bpp, dst_stride;
432
433         if (pp_task_p == NULL) {
434                 return HAL_TDM_ERROR_INVALID_PARAMETER;
435         }
436         LIST_FOR_EACH_ENTRY_SAFE(pp_task, pp_tasks_next, &capture_data->pp_convert_list, link) {
437                 if (pp_task->src_buffer == NULL &&
438                         pp_task->dst_buffer == NULL) {
439                         new_pp_task = pp_task;
440                         new_pp_task->dst_buffer = dst;
441                         new_pp_task->src_buffer = src;
442                         tbm_surface_internal_ref(dst);
443                         tbm_surface_internal_ref(src);
444                         break;
445                 }
446         }
447         if (new_pp_task == NULL) {
448                 new_pp_task = calloc(1, sizeof(tdm_sprd_capture_pp_data));
449                 if (new_pp_task == NULL) {
450                         TDM_BACKEND_WRN("Out of memory");
451                         return HAL_TDM_ERROR_OUT_OF_MEMORY;
452                 }
453                 new_pp_task->dst_buffer = dst;
454                 new_pp_task->src_buffer = src;
455                 tbm_surface_internal_ref(dst);
456                 tbm_surface_internal_ref(src);
457                 LIST_ADD(&new_pp_task->link, &capture_data->pp_convert_list);
458                 pp = tdm_sprd_pp_create(capture_data->display_data, &tdm_err);
459                 if (tdm_err != HAL_TDM_ERROR_NONE) {
460                         TDM_BACKEND_WRN("can't create pp");
461                         goto fail;
462                 }
463                 if ((tdm_err = sprd_pp_set_done_handler(pp, _tdm_sprd_capture_pp_done_handler,
464                                                                                                   capture_data)) != HAL_TDM_ERROR_NONE) {
465                         TDM_BACKEND_WRN("can't create done handler");
466                         goto fail;
467                 }
468                 new_pp_task->pp_link = pp;
469         }
470         CLEAR(info_pp);
471         src_format = tbm_surface_get_format(src);
472         src_bpp = tbm_surface_internal_get_bpp(src_format);
473         src_stride = 0;
474         if (!tbm_surface_internal_get_plane_data(src, 0, NULL, NULL, &src_stride)) {
475                 TDM_BACKEND_WRN("can't get stride");
476                 tdm_err = HAL_TDM_ERROR_OPERATION_FAILED;
477                 goto fail;
478         }
479         if (IS_RGB(src_format)) {
480                 src_bpp >>= 3;
481                 if (src_bpp != 0)
482                         src_stride /= src_bpp;
483         }
484         info_pp.src_config.format = tbm_surface_get_format(src);
485         info_pp.src_config.pos.x = (src_pos) ? src_pos->x : 0;
486         info_pp.src_config.pos.y = (src_pos) ? src_pos->y : 0;
487         info_pp.src_config.pos.w = (src_pos) ? src_pos->w : tbm_surface_get_width(src);
488         info_pp.src_config.pos.h = (src_pos) ? src_pos->h : tbm_surface_get_height(src);
489         info_pp.src_config.size.h = src_stride;
490         info_pp.src_config.size.v = tbm_surface_get_height(src);
491
492         dst_format = tbm_surface_get_format(dst);
493         dst_bpp = tbm_surface_internal_get_bpp(dst_format);
494         dst_stride = 0;
495         if (!tbm_surface_internal_get_plane_data(dst, 0, NULL, NULL, &dst_stride)) {
496                 TDM_BACKEND_WRN("can't get stride");
497                 tdm_err = HAL_TDM_ERROR_OPERATION_FAILED;
498                 goto fail;
499         }
500         if (IS_RGB(dst_format)) {
501                 dst_bpp >>= 3;
502                 if (dst_bpp != 0)
503                         dst_stride /= dst_bpp;
504         }
505
506         info_pp.dst_config.format = dst_format;
507         info_pp.dst_config.pos.x = (dst_pos) ? dst_pos->x : 0;
508         info_pp.dst_config.pos.y = (dst_pos) ? dst_pos->y : 0;
509         info_pp.dst_config.pos.w = (dst_pos) ? dst_pos->w : tbm_surface_get_width(dst);
510         info_pp.dst_config.pos.h = (dst_pos) ? dst_pos->h : tbm_surface_get_height(dst);
511         info_pp.dst_config.size.h = dst_stride;
512         info_pp.dst_config.size.v = tbm_surface_get_height(dst);
513         info_pp.transform = transform;
514         if ((tdm_err = sprd_pp_set_info(new_pp_task->pp_link, &info_pp)) != HAL_TDM_ERROR_NONE) {
515                 TDM_BACKEND_WRN("can't set pp info");
516                 tdm_err = HAL_TDM_ERROR_OPERATION_FAILED;
517                 goto fail;
518         }
519         if ((tdm_err = sprd_pp_attach(new_pp_task->pp_link, src, dst)) != HAL_TDM_ERROR_NONE) {
520                 TDM_BACKEND_WRN("can't set buffers to pp");
521                 tdm_err = HAL_TDM_ERROR_OPERATION_FAILED;
522                 goto fail;
523         }
524         *pp_task_p = new_pp_task;
525         return HAL_TDM_ERROR_NONE;
526
527 fail:
528         if (pp)
529                 sprd_pp_destroy(pp);
530         if (new_pp_task) {
531                 LIST_DEL(&new_pp_task->link);
532                 if (new_pp_task->dst_buffer)
533                         tbm_surface_internal_unref(dst);
534                 if (new_pp_task->src_buffer)
535                         tbm_surface_internal_unref(src);
536                 free(new_pp_task);
537         }
538         return tdm_err;
539 }
540
541 void _tdm_sprd_capture_oneshot_transform_rect(int dpy_w, int dpy_h, hal_tdm_transform transform, hal_tdm_pos *pos)
542 {
543         int temp = 0;
544
545         if (transform == HAL_TDM_TRANSFORM_90) {
546                 temp = pos->x;
547                 pos->x = dpy_h - pos->y - pos->h;
548                 pos->y = temp;
549                 temp = pos->w;
550                 pos->w = pos->h;
551                 pos->h = temp;
552         } else if (transform == HAL_TDM_TRANSFORM_180) {
553                 pos->x = dpy_w - pos->x - pos->w;
554                 pos->y = dpy_h - pos->y - pos->h;
555         } else if (transform == HAL_TDM_TRANSFORM_270) {
556                 temp = pos->y;
557                 pos->y = dpy_w - pos->x - pos->w;
558                 pos->x = temp;
559                 temp = pos->w;
560                 pos->w = pos->h;
561                 pos->h = temp;
562         } else if (transform == HAL_TDM_TRANSFORM_FLIPPED) {
563                 pos->x = dpy_w - pos->x - pos->w;
564         } else if (transform == HAL_TDM_TRANSFORM_FLIPPED_90) {
565                 temp = pos->x;
566                 pos->x = pos->y;
567                 pos->y = temp;
568                 temp = pos->w;
569                 pos->w = pos->h;
570                 pos->h = temp;
571         } else if (transform == HAL_TDM_TRANSFORM_FLIPPED_180) {
572                 pos->y = dpy_h - pos->y - pos->h;
573         } else if (transform == HAL_TDM_TRANSFORM_FLIPPED_270) {
574                 temp = pos->y;
575                 pos->y = dpy_w - pos->x - pos->w;
576                 pos->x = dpy_h - temp - pos->h;
577                 temp = pos->w;
578                 pos->w = pos->h;
579                 pos->h = temp;
580         }
581 }
582
583 static hal_tdm_error
584 _tdm_sprd_capture_oneshot_composite_layers_sw(tdm_sprd_capture_data *capture_data,
585                                                                                           tbm_surface_h buffer)
586 {
587         tbm_surface_info_s buf_info;
588         const hal_tdm_output_mode *current_mode = NULL;
589         tbm_surface_h surface = NULL;
590         tdm_sprd_capture_composite *composite_data = NULL;
591         tdm_sprd_capture_pp_data ** pp_tasks = NULL;
592         int int_err, i;
593         hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
594
595         if ((sprd_output_get_mode(capture_data->output_data, &current_mode)) != HAL_TDM_ERROR_NONE) {
596                 TDM_BACKEND_ERR("can't get output mode");
597                 return HAL_TDM_ERROR_OPERATION_FAILED;
598         }
599         if (current_mode == NULL) {
600                 TDM_BACKEND_WRN("Output mode not init. Can't capture");
601                 return HAL_TDM_ERROR_OPERATION_FAILED;
602         }
603
604         int_err = tbm_surface_get_info(buffer, &buf_info);
605         TDM_BACKEND_RETURN_VAL_IF_FAIL(int_err == TBM_SURFACE_ERROR_NONE, HAL_TDM_ERROR_BAD_REQUEST);
606
607         composite_data = calloc(1, sizeof(tdm_sprd_capture_composite));
608         if (composite_data == NULL) {
609                 TDM_BACKEND_WRN("Out of memory");
610                 tdm_err = HAL_TDM_ERROR_OUT_OF_MEMORY;
611                 goto fail;
612         }
613
614         composite_data->client_buffer = buffer;
615         tbm_surface_internal_ref(buffer);
616         LIST_ADD(&composite_data->link, &capture_data->composite_list);
617         pp_tasks = calloc(NUM_LAYERS, sizeof(tdm_sprd_capture_pp_data *));
618         if (pp_tasks == NULL) {
619                 TDM_BACKEND_WRN("Out of memory");
620                 tdm_err = HAL_TDM_ERROR_OUT_OF_MEMORY;
621                 goto fail;
622         }
623         for (i = 0; i < NUM_LAYERS; ++i) {
624                 tdm_sprd_output *output_data = NULL;
625                 tdm_sprd_layer *layer_data = NULL;
626                 tdm_sprd_layer_info layer_info;
627
628                 output_data = (tdm_sprd_output *)capture_data->output_data;
629                 layer_data = tdm_sprd_output_get_tdm_sprd_layer(output_data, i);
630                 if (!layer_data) continue;
631
632                 CLEAR(layer_info);
633                 if (tdm_sprd_layer_get_info(layer_data, &layer_info) != HAL_TDM_ERROR_NONE) {
634                         TDM_BACKEND_WRN("can't get layer %p info. Skip", layer_data);
635                         continue;
636                 }
637                 if (layer_info.src_config.pos.h == 0 || layer_info.src_config.pos.w == 0) {
638                         TDM_BACKEND_INFO("layer %p info is NULL. Skip", layer_data);
639                         continue;
640                 }
641                 if (tdm_sprd_layer_get_buffer(layer_data, &surface) != HAL_TDM_ERROR_NONE) {
642                         TDM_BACKEND_WRN("can't get layer %p surface. Skip", layer_data);
643                         continue;
644                 }
645                 if (surface == NULL) {
646                         TDM_BACKEND_INFO("layer %p buffer is NULL. Skip", layer_data);
647                         continue;
648                 }
649                 tbm_surface_internal_ref(surface);
650                 TDM_BACKEND_DBG("Get layer %p surface %p", layer_data, surface);
651                 if (1) {
652
653                         int output_width = current_mode->hdisplay;
654                         int width = layer_info.src_config.pos.w;
655                         int pos_x = layer_info.dst_pos.x;
656                         hal_tdm_pos scale_pos = {.x = pos_x, .y = layer_info.dst_pos.y,
657                                            .w = ((width + pos_x) <= output_width ? width : output_width - pos_x),
658                                            .h = layer_info.src_config.pos.h};
659                         hal_tdm_pos src_pos = layer_info.src_config.pos;
660                         hal_tdm_pos dst_pos = capture_data->info.dst_config.pos;
661
662                         TDM_BACKEND_DBG("src_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", src_pos.x, src_pos.y,
663                                         src_pos.w, src_pos.h);
664                         TDM_BACKEND_DBG("dst_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", dst_pos.x, dst_pos.y,
665                                         dst_pos.w, dst_pos.h);
666                         TDM_BACKEND_DBG("scale_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", scale_pos.x, scale_pos.y,
667                                         scale_pos.w, scale_pos.h);
668                         if (dst_pos.w == 0 || dst_pos.h == 0) {
669                                 dst_pos.x = 0;
670                                 dst_pos.y = 0;
671                                 dst_pos.h = tbm_surface_get_height(buffer);
672                                 dst_pos.w = tbm_surface_get_width(buffer);
673
674                                 if (dst_pos.w == 0 || dst_pos.h == 0) {
675                                         TDM_BACKEND_WRN("dst_pos size is zero");
676                                         tbm_surface_internal_unref(surface);
677                                         continue;
678                                 }
679
680                                 _tdm_sprd_capture_oneshot_center_rect(current_mode->hdisplay,
681                                                                                                           current_mode->vdisplay,
682                                                                                                           dst_pos.w, dst_pos.h, &dst_pos);
683
684                                 TDM_BACKEND_DBG("--> new_dst_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", dst_pos.x, dst_pos.y,
685                                                 dst_pos.w, dst_pos.h);
686                         }
687
688                         _tdm_sprd_capture_oneshot_transform_rect(current_mode->hdisplay,
689                                                                                                          current_mode->vdisplay,
690                                                                                                          capture_data->info.transform,
691                                                                                                          &scale_pos);
692
693                         if (capture_data->info.transform & 1) {
694                                 _tdm_sprd_capture_oneshot_rect_scale(current_mode->vdisplay,
695                                                                                                          current_mode->hdisplay,
696                                                                                                          dst_pos.w, dst_pos.h, &scale_pos);
697                         } else {
698                                 _tdm_sprd_capture_oneshot_rect_scale(current_mode->hdisplay,
699                                                                                                          current_mode->vdisplay,
700                                                                                                          dst_pos.w, dst_pos.h, &scale_pos);
701                         }
702
703                         TDM_BACKEND_DBG("scale_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", scale_pos.x, scale_pos.y,
704                                         scale_pos.w, scale_pos.h);
705 /*
706                         if (capture_data->info.transform & 1) {
707
708                         }
709 */
710                         tbm_surface_h temp_buffer = tbm_surface_create(dst_pos.w,
711                                                                                                                    dst_pos.h,
712                                                                                                                    TBM_FORMAT_ARGB8888);
713                         if (temp_buffer == NULL) {
714                                 TDM_BACKEND_WRN("Out of memory");
715                                 tbm_surface_internal_unref(surface);
716                                 continue;
717                         }
718
719                         dst_pos.x += scale_pos.x;
720                         dst_pos.y += scale_pos.y;
721                         dst_pos.h = scale_pos.h;
722                         dst_pos.w = scale_pos.w;
723
724                         TDM_BACKEND_DBG("adapted dst_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", dst_pos.x, dst_pos.y,
725                                         dst_pos.w, dst_pos.h);
726
727                         tdm_err = _tdm_sprd_capture_make_converter(capture_data, surface, temp_buffer,
728                                                                                                            &src_pos, NULL, capture_data->info.transform,
729                                                                                                            &pp_tasks[i]);
730                         if (tdm_err != HAL_TDM_ERROR_NONE) {
731                                 TDM_BACKEND_WRN("can't create converter");
732                                 tbm_surface_internal_unref(surface);
733                                 tbm_surface_internal_unref(temp_buffer);
734                                 continue;
735                         }
736
737                         int zpos;
738                         if (tdm_sprd_layer_get_zpos(layer_data, &zpos) != HAL_TDM_ERROR_NONE) {
739                                 TDM_BACKEND_WRN("can't get layer %p zpos", layer_data);
740                                 _tdm_sprd_capture_destroy_converter(&pp_tasks[i]);
741                                 tbm_surface_internal_unref(surface);
742                                 tbm_surface_internal_unref(temp_buffer);
743                                 continue;
744                         }
745                         composite_data->temp_layer_buffer[i] = temp_buffer;
746                         composite_data->dst_pos[i] = dst_pos;
747                         composite_data->zpos[i] = zpos;
748                         composite_data->need_done_buf_num++;
749                 }
750                 tbm_surface_internal_unref(surface);
751         }
752
753         if (!composite_data->need_done_buf_num) {
754                 TDM_BACKEND_INFO("Layers buffer are empty. Nothing to do");
755                 tdm_err = HAL_TDM_ERROR_NONE;
756                 goto fail;
757         }
758
759         if (!IS_RGB(tbm_surface_get_format(composite_data->client_buffer))) {
760                 tdm_sprd_capture_pp_data * pp_task = NULL;
761                 composite_data->temp_composite_buffer = tbm_surface_create(tbm_surface_get_width(buffer),
762                                                                                                            tbm_surface_get_height(buffer),
763                                                                                                            TBM_FORMAT_ARGB8888);
764                 if (composite_data->temp_composite_buffer == NULL) {
765                         TDM_BACKEND_WRN("Out of memory");
766                         tdm_err = HAL_TDM_ERROR_OUT_OF_MEMORY;
767                         goto fail;
768                 }
769                 tdm_err = _tdm_sprd_capture_make_converter(capture_data, composite_data->temp_composite_buffer,
770                                                                                                    composite_data->client_buffer,
771                                                                                                    NULL, NULL, 0, &pp_task);
772                 if (tdm_err != HAL_TDM_ERROR_NONE) {
773                         TDM_BACKEND_WRN("can't create converter");
774                         goto fail;
775                 }
776                 composite_data->composite_buf_pp_task = pp_task;
777         }
778         for (i = 0; i < NUM_LAYERS; i++) {
779                 if (pp_tasks[i]) {
780                         tdm_err = sprd_pp_commit(pp_tasks[i]->pp_link);
781                         if (tdm_err != HAL_TDM_ERROR_NONE) {
782                                 composite_data->need_done_buf_num--;
783                                 _tdm_sprd_capture_destroy_converter(&pp_tasks[i]);
784                                 tbm_surface_internal_unref(composite_data->temp_layer_buffer[i]);
785                                 composite_data->temp_layer_buffer[i] = NULL;
786                         }
787                 }
788         }
789         if (!composite_data->need_done_buf_num) {
790                 TDM_BACKEND_WRN("Can't capture layers");
791                 goto fail;
792         }
793         if (pp_tasks) {
794                 free(pp_tasks);
795         }
796
797         return HAL_TDM_ERROR_NONE;
798
799 fail:
800         if (pp_tasks) {
801                 for (i = 0; i < NUM_LAYERS; ++i) {
802                         if (pp_tasks[i])
803                                 _tdm_sprd_capture_destroy_converter(&pp_tasks[i]);
804                 }
805                 free(pp_tasks);
806         }
807         if (composite_data) {
808                 LIST_DEL(&composite_data->link);
809                 if (composite_data->composite_buf_pp_task) {
810                         _tdm_sprd_capture_destroy_converter(&composite_data->composite_buf_pp_task);
811                 }
812                 if (composite_data->temp_composite_buffer != NULL) {
813                         tbm_surface_internal_unref(composite_data->temp_composite_buffer);
814                 }
815                 for (i = 0; i < LAYER_COUNT_PER_OUTPUT; i++) {
816                         if (composite_data->temp_layer_buffer[i] != NULL) {
817                                 tbm_surface_internal_unref(composite_data->temp_layer_buffer[i]);
818                         }
819                 }
820                 if (composite_data->client_buffer != NULL) {
821                         tbm_surface_internal_unref(composite_data->client_buffer);
822                         if (capture_data->done_func) {
823                                 capture_data->done_func(capture_data,
824                                                                                 composite_data->client_buffer,
825                                                                                 capture_data->done_user_data);
826                         }
827                         composite_data->client_buffer = NULL;
828                 }
829                 free(composite_data);
830         }
831
832         return tdm_err;
833 }
834
835 static hal_tdm_error
836 _tdm_sprd_capture_set_timer(tdm_sprd_capture_data *capture_data)
837 {
838         struct itimerspec timeout;
839         int ret = 0;
840
841         timeout.it_value.tv_sec = timeout.it_interval.tv_sec = 0;
842         timeout.it_value.tv_nsec = 30000000;
843         timeout.it_interval.tv_nsec = 0;
844
845         ret = timerfd_settime(g_capture_data->timer_fd, 0, &timeout, NULL);
846         if (ret) {
847                 TDM_BACKEND_ERR("timerfd_settime fail : %d", errno);
848                 return HAL_TDM_ERROR_OPERATION_FAILED;
849         }
850
851         TDM_BACKEND_DBG("set timer %llu", timeout.it_interval.tv_nsec);
852
853         return HAL_TDM_ERROR_NONE;
854 }
855
856 static hal_tdm_error
857 _tdm_sprd_capture_stop_timer(void)
858 {
859         struct itimerspec timeout;
860         int ret = 0;
861
862         timeout.it_value.tv_sec = timeout.it_interval.tv_sec = 0;
863         timeout.it_value.tv_nsec = timeout.it_interval.tv_nsec = 0;
864
865         ret = timerfd_settime(g_capture_data->timer_fd, 0, &timeout, NULL);
866         if (ret) {
867                 TDM_BACKEND_ERR("timerfd_settime stop fail : %d", errno);
868                 return HAL_TDM_ERROR_OPERATION_FAILED;
869         }
870
871         TDM_BACKEND_DBG("stop timer");
872
873         return HAL_TDM_ERROR_NONE;
874 }
875
876
877 void
878 sprd_capture_destroy(hal_tdm_capture *capture)
879 {
880         tdm_sprd_capture_data *capture_data = capture;
881         if (!_tdm_sprd_capture_check_struct(capture_data)) {
882                 return;
883         }
884         tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
885         tdm_sprd_capture_pp_data  *pp_task = NULL, *pp_tasks_next = NULL;
886         tdm_sprd_capture_composite *composite = NULL, *composite_next = NULL;
887         int i;
888         capture_data->removing = 1;
889         TDM_BACKEND_DBG("capture(%p) destroy", capture_data);
890
891         LIST_FOR_EACH_ENTRY_SAFE(pp_task, pp_tasks_next, &capture_data->pp_convert_list, link) {
892                 _tdm_sprd_capture_destroy_converter(&pp_task);
893         }
894
895         LIST_FOR_EACH_ENTRY_SAFE(composite, composite_next, &capture_data->composite_list, link) {
896                 LIST_DEL(&composite->link);
897                 for (i = 0; i < LAYER_COUNT_PER_OUTPUT; i++) {
898                         if (composite->temp_layer_buffer[i]) {
899                                 tbm_surface_internal_unref(composite->temp_layer_buffer[i]);
900                                 composite->temp_layer_buffer[i] = NULL;
901                         }
902                 }
903                 if (composite->client_buffer) {
904                         tbm_surface_internal_unref(composite->client_buffer);
905                         if (capture_data->done_func) {
906                                 capture_data->done_func(capture_data,
907                                                                                 composite->client_buffer,
908                                                                                 capture_data->done_user_data);
909                         }
910                         composite->client_buffer = NULL;
911                 }
912                 if (composite->temp_composite_buffer) {
913                         tbm_surface_internal_unref(composite->temp_composite_buffer);
914                         composite->temp_composite_buffer = NULL;
915                 }
916                 free(composite);
917         }
918         LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
919                 LIST_DEL(&b->link);
920                 if (capture_data->done_func) {
921                         capture_data->done_func(capture_data,
922                                                                         b->buffer,
923                                                                         capture_data->done_user_data);
924                 }
925                 free(b);
926         }
927
928         if (g_capture_data->stream_data == capture_data) {
929                 TDM_BACKEND_DBG("stream capture %p remove", capture_data);
930                 g_capture_data->stream_data = NULL;
931                 g_capture_data->timer_running = 0;
932                 _tdm_sprd_capture_stop_timer();
933         }
934
935         LIST_DEL(&capture_data->link);
936         capture_data->stamp = 0;
937         tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
938         free(capture_data);
939 }
940
941 static hal_tdm_error
942 _tdm_sprd_capture_commit_stream(tdm_sprd_capture_data *capture_data)
943 {
944         hal_tdm_error ret;
945
946         if (g_capture_data->timer_fd == -1) {
947                 TDM_BACKEND_ERR("cannot support stream capture");
948                 return HAL_TDM_ERROR_BAD_REQUEST;
949         }
950
951         if ((g_capture_data->stream_data != NULL) && (g_capture_data->stream_data != capture_data)) {
952                 TDM_BACKEND_ERR("previous stream capture is working. cannot execute.");
953                 return HAL_TDM_ERROR_BUSY;
954         }
955
956         if (g_capture_data->timer_running) {
957                 TDM_BACKEND_DBG("stream capture is working");
958                 return HAL_TDM_ERROR_NONE;
959         }
960
961         ret = _tdm_sprd_capture_set_timer(capture_data);
962         if (ret != HAL_TDM_ERROR_NONE) {
963                 TDM_BACKEND_ERR("timerfd_settime fail: %d", ret);
964                 return HAL_TDM_ERROR_OPERATION_FAILED;
965         }
966
967         g_capture_data->timer_running = 1;
968         g_capture_data->stream_data = capture_data;
969
970         TDM_BACKEND_DBG("stream capture start");
971
972         return HAL_TDM_ERROR_NONE;
973 }
974
975 static hal_tdm_error
976 _tdm_sprd_capture_commit_oneshot(tdm_sprd_capture_data *capture_data)
977 {
978         tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
979         tbm_surface_h current_buffer = NULL;
980         hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
981         LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
982                 LIST_DEL(&b->link);
983                 current_buffer = b->buffer;
984                 tbm_surface_internal_ref(b->buffer);
985                 free(b);
986                 tdm_err = _tdm_sprd_capture_oneshot_composite_layers_sw(capture_data, current_buffer);
987                 tbm_surface_internal_unref(current_buffer);
988                 if (tdm_err != HAL_TDM_ERROR_NONE) {
989                         TDM_BACKEND_ERR("capture %p composite func return err %d", tdm_err);
990                         break;
991                 }
992         }
993         return tdm_err;
994 }
995
996 hal_tdm_error
997 sprd_display_get_capture_capability(hal_tdm_display *display, hal_tdm_caps_capture *caps)
998 {
999         int i;
1000         tdm_sprd_display *display_data = NULL;
1001
1002         if (!caps || !display) {
1003                 TDM_BACKEND_ERR("invalid params");
1004                 return HAL_TDM_ERROR_INVALID_PARAMETER;
1005         }
1006
1007         display_data = (tdm_sprd_display *)display;
1008
1009         caps->capabilities = HAL_TDM_CAPTURE_CAPABILITY_OUTPUT|
1010                                                  HAL_TDM_CAPTURE_CAPABILITY_ONESHOT;
1011         if (display_data->timer_fd != -1)
1012                 caps->capabilities |= HAL_TDM_CAPTURE_CAPABILITY_STREAM;
1013
1014         caps->format_count = NUM_CAPTURE_FORMAT;
1015         caps->formats = NULL;
1016         if (NUM_CAPTURE_FORMAT) {
1017                 /* will be freed in frontend */
1018                 caps->formats = calloc(1, sizeof capture_client_formats);
1019                 if (!caps->formats) {
1020                         TDM_BACKEND_ERR("alloc failed");
1021                         return HAL_TDM_ERROR_OUT_OF_MEMORY;
1022                 }
1023                 for (i = 0; i < caps->format_count; i++)
1024                         caps->formats[i] = capture_client_formats[i];
1025         }
1026
1027         caps->min_w = 16;
1028         caps->min_h = 8;
1029         caps->preferred_align = 2;
1030
1031         return HAL_TDM_ERROR_NONE;
1032 }
1033
1034 hal_tdm_capture*
1035 sprd_output_create_capture(hal_tdm_output *output, hal_tdm_error *error)
1036 {
1037         if (!output) {
1038                 TDM_BACKEND_ERR("invalid params");
1039                 if (error) {
1040                         *error = HAL_TDM_ERROR_INVALID_PARAMETER;
1041                 }
1042                 return NULL;
1043         }
1044         tdm_sprd_capture_data *capture_data = calloc(1, sizeof(tdm_sprd_capture_data));
1045         if (!capture_data) {
1046                 TDM_BACKEND_ERR("alloc failed");
1047                 if (error)
1048                         *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
1049                 return NULL;
1050         }
1051
1052         if ((capture_data->display_data = tdm_sprd_output_get_display(output)) == NULL) {
1053                 TDM_BACKEND_ERR("invalid params");
1054                 if (error)
1055                         *error = HAL_TDM_ERROR_INVALID_PARAMETER;
1056                 goto fail;
1057         }
1058
1059         if ((tdm_sprd_output_attach_capture(output, capture_data)) != HAL_TDM_ERROR_NONE) {
1060                 TDM_BACKEND_ERR("can't attach capture to output");
1061                 if (error)
1062                         *error = HAL_TDM_ERROR_OPERATION_FAILED;
1063                 goto fail;
1064         }
1065         capture_data->output_data = output;
1066         capture_data->stamp = capture_stamp++;
1067         LIST_INITHEAD(&capture_data->pending_buffer_list);
1068         LIST_INITHEAD(&capture_data->pp_convert_list);
1069         LIST_INITHEAD(&capture_data->composite_list);
1070
1071         if (!capture_list_init) {
1072                 capture_list_init = 1;
1073                 LIST_INITHEAD(&capture_list);
1074         }
1075         LIST_ADDTAIL(&capture_data->link, &capture_list);
1076         TDM_BACKEND_DBG("capture(%p) create", capture_data);
1077         if (error) {
1078                 *error = HAL_TDM_ERROR_NONE;
1079         }
1080         return capture_data;
1081 fail:
1082         if (capture_data)
1083                 free(capture_data);
1084         return NULL;
1085 }
1086
1087 hal_tdm_error
1088 sprd_capture_set_info(hal_tdm_capture *capture, hal_tdm_info_capture *info)
1089 {
1090         tdm_sprd_capture_data *capture_data = capture;
1091         if (!_tdm_sprd_capture_check_struct(capture_data)) {
1092                 return HAL_TDM_ERROR_INVALID_PARAMETER;
1093         }
1094         if (capture_data->removing) {
1095                 TDM_BACKEND_INFO("Capture removing. Skip call func");
1096                 return HAL_TDM_ERROR_BUSY;
1097         }
1098         TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
1099
1100         capture_data->info = *info;
1101         capture_data->info_changed = 1;
1102
1103         return HAL_TDM_ERROR_NONE;
1104 }
1105
1106 hal_tdm_error
1107 sprd_capture_attach(hal_tdm_capture *capture, tbm_surface_h buffer)
1108 {
1109         tdm_sprd_capture_data *capture_data = capture;
1110         tdm_sprd_capture_buffer *b;
1111         if (!_tdm_sprd_capture_check_struct(capture_data)) {
1112                 return HAL_TDM_ERROR_INVALID_PARAMETER;
1113         }
1114         if (capture_data->removing) {
1115                 TDM_BACKEND_INFO("Capture removing. Skip call func");
1116                 return HAL_TDM_ERROR_BUSY;
1117         }
1118         TDM_BACKEND_RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_INVALID_PARAMETER);
1119         b = calloc(1, sizeof(tdm_sprd_capture_buffer));
1120         if (!b) {
1121                 TDM_BACKEND_ERR("alloc failed");
1122                 return HAL_TDM_ERROR_NONE;
1123         }
1124         TDM_BACKEND_DBG("capture %p attach buffer %p", capture, buffer);
1125         LIST_ADDTAIL(&b->link, &capture_data->pending_buffer_list);
1126
1127         b->buffer = buffer;
1128
1129         return HAL_TDM_ERROR_NONE;
1130 }
1131
1132 hal_tdm_error
1133 sprd_capture_commit(hal_tdm_capture *capture)
1134 {
1135         tdm_sprd_capture_data *capture_data = capture;
1136         hal_tdm_error ret;
1137         if (!_tdm_sprd_capture_check_struct(capture_data)) {
1138                 return HAL_TDM_ERROR_INVALID_PARAMETER;
1139         }
1140         if (capture_data->removing) {
1141                 TDM_BACKEND_INFO("Capture removing. Skip call func");
1142                 return HAL_TDM_ERROR_BUSY;
1143         }
1144         TDM_BACKEND_DBG("capture %p commit", capture);
1145         if (capture_data->info.type == HAL_TDM_CAPTURE_TYPE_ONESHOT)
1146                 ret = _tdm_sprd_capture_commit_oneshot(capture_data);
1147         else
1148                 ret = _tdm_sprd_capture_commit_stream(capture_data);
1149
1150         return ret;
1151 }
1152
1153 hal_tdm_error
1154 sprd_capture_set_done_handler(hal_tdm_capture *capture, hal_tdm_capture_done_handler func, void *user_data)
1155 {
1156         tdm_sprd_capture_data *capture_data = capture;
1157
1158         if (!_tdm_sprd_capture_check_struct(capture_data)) {
1159                 return HAL_TDM_ERROR_INVALID_PARAMETER;
1160         }
1161         if (capture_data->removing) {
1162                 TDM_BACKEND_INFO("Capture removing. Skip call func");
1163                 return HAL_TDM_ERROR_BUSY;
1164         }
1165         TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1166
1167         capture_data->done_func = func;
1168         capture_data->done_user_data = user_data;
1169         TDM_BACKEND_DBG("capture %p set done handler func %p", capture, func);
1170         return HAL_TDM_ERROR_NONE;
1171 }
1172
1173 hal_tdm_error
1174 tdm_sprd_capture_init(tdm_sprd_display *display_data)
1175 {
1176         tdm_sprd_capture_internal *capture_data_internal = calloc(1, sizeof(tdm_sprd_capture_internal));
1177         if (!capture_data_internal) {
1178                 TDM_BACKEND_ERR("alloc failed");
1179
1180                 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1181         }
1182         capture_data_internal->timer_fd = display_data->timer_fd;
1183
1184         g_capture_data = capture_data_internal;
1185
1186         return HAL_TDM_ERROR_NONE;
1187 }
1188
1189 void
1190 tdm_sprd_capture_deinit(tdm_sprd_display *display_data)
1191 {
1192         if (g_capture_data == NULL)
1193                 return;
1194
1195         free(g_capture_data);
1196         g_capture_data = NULL;
1197 }
1198
1199 void
1200 tdm_sprd_capture_timer_cb(tdm_sprd_display *display_data)
1201 {
1202         tdm_sprd_capture_data *capture_data = NULL;
1203         tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
1204         tbm_surface_h current_buffer = NULL;
1205         uint64_t buf;
1206         int expired = read(display_data->timer_fd, &buf, sizeof(uint64_t));
1207         if (expired < 0)
1208                 TDM_BACKEND_ERR("read fail");
1209
1210         if (!g_capture_data)
1211                 return;
1212
1213         g_capture_data->timer_running = 0;
1214
1215         if(!g_capture_data->stream_data)
1216                 return;
1217
1218         capture_data = g_capture_data->stream_data;
1219         if (!_tdm_sprd_capture_check_struct(capture_data))
1220                 return;
1221
1222         if (capture_data->removing) {
1223                 TDM_BACKEND_INFO("Capture %p Postponded removing", capture_data);
1224                 _tdm_sprd_capture_stop_timer();
1225                 g_capture_data->timer_running = 0;
1226                 g_capture_data->stream_data = NULL;
1227                 LIST_DEL(&capture_data->link);
1228                 capture_data->stamp = 0;
1229                 tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
1230                 free(capture_data);
1231                 return;
1232         }
1233
1234         if (!LIST_IS_EMPTY(&capture_data->composite_list)) {
1235                 TDM_BACKEND_DBG("Converter is busy");
1236                 return;
1237         }
1238         LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
1239                 LIST_DEL(&b->link);
1240                 current_buffer = b->buffer;
1241                 tbm_surface_internal_ref(current_buffer);
1242                 free(b);
1243                 _tdm_sprd_capture_oneshot_composite_layers_sw(capture_data, current_buffer);
1244                 tbm_surface_internal_unref(current_buffer);
1245                 break;
1246         }
1247 }