• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  * Copyright@ Samsung Electronics Co. LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*!
19  * \file      exynos_rotator.c
20  * \brief     source file for exynos_rotator HAL
21  * \author    Sunmi Lee (carrotsm.lee@samsung.com)
22  * \date      2012/03/05
23  *
24  * <b>Revision History: </b>
25  * - 2012/03/05 : Sunmi Lee (carrotsm.lee@samsung.com) \n
26  *   Create
27  *
28  */
29 
30 //#define LOG_NDEBUG 0
31 #define LOG_TAG "libexynosrotator"
32 #include <cutils/log.h>
33 
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
36 #include <videodev2.h>
37 #include <fcntl.h>
38 #include <stdbool.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <time.h>
44 
45 #include "exynos_rotator.h"
46 
47 #include "exynos_format.h"
48 #include "ExynosMutex.h"
49 #include "exynos_v4l2.h"
50 
51 #define NUM_OF_ROTATOR_PLANES           (3)
52 #define NODE_NUM_ROTATOR                (21)
53 #define PFX_NODE_ROTATOR                "/dev/video"
54 
55 #define ROTATOR_MIN_W_SIZE (8)
56 #define ROTATOR_MIN_H_SIZE (8)
57 
58 #define MAX_ROTATOR_WAITING_TIME_FOR_TRYLOCK (16000) // 16msec
59 #define ROTATOR_WAITING_TIME_FOR_TRYLOCK      (8000) //  8msec
60 
61 struct rotator_info {
62     unsigned int       width;
63     unsigned int       height;
64     unsigned int       crop_left;
65     unsigned int       crop_top;
66     unsigned int       crop_width;
67     unsigned int       crop_height;
68     unsigned int       v4l2_colorformat;
69     unsigned int       cacheable;
70 
71     int                rotation;
72 
73     void              *addr[NUM_OF_ROTATOR_PLANES];
74     bool               stream_on;
75 
76     enum v4l2_buf_type buf_type;
77     struct v4l2_format format;
78     struct v4l2_buffer buffer;
79     struct v4l2_plane  planes[NUM_OF_ROTATOR_PLANES];
80     struct v4l2_crop   crop;
81 };
82 
83 struct ROTATOR_HANDLE {
84     int              rotator_fd;
85     struct rotator_info  src;
86     struct rotator_info  dst;
87     void                *op_mutex;
88     void                *obj_mutex;
89     void                *cur_obj_mutex;
90 };
91 
m_rotator_get_plane_count(int v4l_pixel_format)92 static unsigned int m_rotator_get_plane_count(
93     int v4l_pixel_format)
94 {
95     int plane_count = 0;
96 
97     switch (v4l_pixel_format) {
98     case V4L2_PIX_FMT_RGB32:
99     case V4L2_PIX_FMT_BGR32:
100     case V4L2_PIX_FMT_RGB24:
101     case V4L2_PIX_FMT_RGB565:
102     case V4L2_PIX_FMT_RGB555X:
103     case V4L2_PIX_FMT_RGB444:
104         plane_count = 1;
105         break;
106     case V4L2_PIX_FMT_NV12M:
107     case V4L2_PIX_FMT_NV12MT_16X16:
108     case V4L2_PIX_FMT_NV21:
109     case V4L2_PIX_FMT_NV16:
110     case V4L2_PIX_FMT_NV61:
111         plane_count = 2;
112         break;
113     case V4L2_PIX_FMT_YVU420M:
114     case V4L2_PIX_FMT_YUV422P:
115     case V4L2_PIX_FMT_YUYV:
116     case V4L2_PIX_FMT_UYVY:
117         plane_count = 3;
118         break;
119     default:
120         ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)",
121              __func__, v4l_pixel_format);
122         plane_count = -1;
123         break;
124     }
125 
126     return plane_count;
127 }
128 
m_rotator_get_plane_size(unsigned int * plane_size,unsigned int width,unsigned int height,int v4l_pixel_format)129 static unsigned int m_rotator_get_plane_size(
130     unsigned int *plane_size,
131     unsigned int  width,
132     unsigned int  height,
133     int           v4l_pixel_format)
134 {
135     switch (v4l_pixel_format) {
136     case V4L2_PIX_FMT_RGB32:
137     case V4L2_PIX_FMT_BGR32:
138         plane_size[0] = width * height * 4;
139         break;
140     case V4L2_PIX_FMT_RGB24:
141         plane_size[0] = width * height * 3;
142         break;
143     case V4L2_PIX_FMT_RGB565:
144     case V4L2_PIX_FMT_RGB555X:
145     case V4L2_PIX_FMT_RGB444:
146         plane_size[0] = width * height * 2;
147         break;
148     case V4L2_PIX_FMT_NV12M:
149     case V4L2_PIX_FMT_NV21:
150     case V4L2_PIX_FMT_NV16:
151     case V4L2_PIX_FMT_NV61:
152         plane_size[0] = width * height;
153         plane_size[1] = width * (height / 2);
154         break;
155     case V4L2_PIX_FMT_NV12MT_16X16:
156         plane_size[0] = ALIGN(width, 16) * ALIGN(height, 16);
157         plane_size[1] = ALIGN(width, 16) * ALIGN(height / 2, 8);
158         break;
159     case V4L2_PIX_FMT_YVU420M:
160     case V4L2_PIX_FMT_YUV422P:
161     case V4L2_PIX_FMT_YUYV:
162     case V4L2_PIX_FMT_UYVY:
163         plane_size[0] = width * height;
164         plane_size[1] = (width / 2) * (height / 2);
165         plane_size[2] = (width / 2) * (height / 2);
166         break;
167     default:
168         ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)",
169              __func__, v4l_pixel_format);
170         return -1;
171         break;
172     }
173 
174     return 0;
175 }
176 
m_exynos_rotator_multiple_of_n(int number,int N)177 static int m_exynos_rotator_multiple_of_n(
178     int number, int N)
179 {
180     int result = number;
181     switch (N) {
182     case 1:
183     case 2:
184     case 4:
185     case 8:
186     case 16:
187     case 32:
188     case 64:
189     case 128:
190     case 256:
191         result = (number - (number & (N-1)));
192         break;
193     default:
194         result = number - (number % N);
195         break;
196     }
197     return result;
198 }
199 
m_exynos_rotator_check_src_size(unsigned int * w,unsigned int * h,unsigned int * crop_x,unsigned int * crop_y,unsigned int * crop_w,unsigned int * crop_h,int v4l2_colorformat)200 static bool m_exynos_rotator_check_src_size(
201     unsigned int *w,      unsigned int *h,
202     unsigned int *crop_x, unsigned int *crop_y,
203     unsigned int *crop_w, unsigned int *crop_h,
204     int v4l2_colorformat)
205 {
206     if (*w < ROTATOR_MIN_W_SIZE || *h < ROTATOR_MIN_H_SIZE) {
207         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
208             __func__, ROTATOR_MIN_W_SIZE, *w, ROTATOR_MIN_H_SIZE, *h);
209         return false;
210     }
211 
212     if (*crop_w < ROTATOR_MIN_W_SIZE || *crop_h < ROTATOR_MIN_H_SIZE) {
213         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
214             __func__, ROTATOR_MIN_W_SIZE,* crop_w, ROTATOR_MIN_H_SIZE, *crop_h);
215         return false;
216     }
217 
218     switch (v4l2_colorformat) {
219     // YUV420 3p
220     case V4L2_PIX_FMT_YUV420M:
221     case V4L2_PIX_FMT_YVU420M:
222         *w = ALIGN(*w, 16);
223         *h = ALIGN(*h, 16);
224         break;
225     // YUV420 2p
226     case V4L2_PIX_FMT_NV12M:
227     case V4L2_PIX_FMT_NV12MT:
228     case V4L2_PIX_FMT_NV21M:
229         *w = ALIGN(*w, 8);
230         *h = ALIGN(*h, 8);
231         break;
232     // YUV422
233     case V4L2_PIX_FMT_YUYV:
234     case V4L2_PIX_FMT_YUV422P:
235     case V4L2_PIX_FMT_UYVY:
236     case V4L2_PIX_FMT_NV21:
237     case V4L2_PIX_FMT_NV16:
238     case V4L2_PIX_FMT_YVYU:
239     case V4L2_PIX_FMT_VYUY:
240     // RGB
241     case V4L2_PIX_FMT_RGB32:
242     case V4L2_PIX_FMT_RGB24:
243     case V4L2_PIX_FMT_RGB565:
244     case V4L2_PIX_FMT_BGR32:
245     case V4L2_PIX_FMT_RGB555X:
246     case V4L2_PIX_FMT_RGB444:
247     default:
248         *w = ALIGN(*w, 4);
249         *h = ALIGN(*h, 4);
250         break;
251     }
252     *crop_w = m_exynos_rotator_multiple_of_n(*crop_w, 4);
253     *crop_h = m_exynos_rotator_multiple_of_n(*crop_h, 4);
254 
255     return true;
256 }
257 
m_exynos_rotator_check_dst_size(unsigned int * w,unsigned int * h,unsigned int * crop_x,unsigned int * crop_y,unsigned int * crop_w,unsigned int * crop_h,int v4l2_colorformat,int rotation)258 static bool m_exynos_rotator_check_dst_size(
259     unsigned int *w,      unsigned int *h,
260     unsigned int *crop_x, unsigned int *crop_y,
261     unsigned int *crop_w, unsigned int *crop_h,
262     int v4l2_colorformat,
263     int rotation)
264 {
265     unsigned int *new_w;
266     unsigned int *new_h;
267     unsigned int *new_crop_w;
268     unsigned int *new_crop_h;
269 
270     if (rotation == 90 || rotation == 270) {
271         new_w = h;
272         new_h = w;
273         new_crop_w = crop_h;
274         new_crop_h = crop_w;
275     } else {
276         new_w = w;
277         new_h = h;
278         new_crop_w = crop_w;
279         new_crop_h = crop_h;
280     }
281 
282     if (*w < ROTATOR_MIN_W_SIZE || *h < ROTATOR_MIN_H_SIZE) {
283         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
284             __func__, ROTATOR_MIN_W_SIZE, *w, ROTATOR_MIN_H_SIZE, *h);
285         return false;
286     }
287 
288     if (*crop_w < ROTATOR_MIN_W_SIZE || *crop_h < ROTATOR_MIN_H_SIZE) {
289         ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
290             __func__, ROTATOR_MIN_W_SIZE,* crop_w, ROTATOR_MIN_H_SIZE, *crop_h);
291         return false;
292     }
293 
294     switch (v4l2_colorformat) {
295     // YUV420 3p
296     case V4L2_PIX_FMT_YUV420M:
297     case V4L2_PIX_FMT_YVU420M:
298         *new_w = ALIGN(*new_w, 16);
299         *new_h = ALIGN(*new_h, 16);
300         break;
301     // YUV420 2p
302     case V4L2_PIX_FMT_NV12M:
303     case V4L2_PIX_FMT_NV12MT:
304     case V4L2_PIX_FMT_NV21M:
305         *new_w = ALIGN(*new_w, 8);
306         *new_h = ALIGN(*new_h, 8);
307         break;
308     // YUV422
309     case V4L2_PIX_FMT_YUYV:
310     case V4L2_PIX_FMT_YUV422P:
311     case V4L2_PIX_FMT_UYVY:
312     case V4L2_PIX_FMT_NV21:
313     case V4L2_PIX_FMT_NV16:
314     case V4L2_PIX_FMT_YVYU:
315     case V4L2_PIX_FMT_VYUY:
316     // RGB
317     case V4L2_PIX_FMT_RGB32:
318     case V4L2_PIX_FMT_RGB24:
319     case V4L2_PIX_FMT_RGB565:
320     case V4L2_PIX_FMT_BGR32:
321     case V4L2_PIX_FMT_RGB555X:
322     case V4L2_PIX_FMT_RGB444:
323     default:
324         *new_w = ALIGN(*new_w, 4);
325         *new_h = ALIGN(*new_h, 4);
326         break;
327     }
328     *new_crop_w = m_exynos_rotator_multiple_of_n(*new_crop_w, 4);
329     *new_crop_h = m_exynos_rotator_multiple_of_n(*new_crop_h, 4);
330 
331     return true;
332 }
333 
m_exynos_rotator_create(void)334 static int m_exynos_rotator_create(void)
335 {
336     int          fd = 0;
337     unsigned int cap;
338     char         node[32];
339 
340     sprintf(node, "%s%d", PFX_NODE_ROTATOR, NODE_NUM_ROTATOR);
341     fd = exynos_v4l2_open(node, O_RDWR);
342     if (fd < 0) {
343         ALOGE("%s::exynos_v4l2_open(%s) fail", __func__, node);
344         return -1;
345     }
346 
347     cap = V4L2_CAP_STREAMING |
348           V4L2_CAP_VIDEO_OUTPUT_MPLANE |
349           V4L2_CAP_VIDEO_CAPTURE_MPLANE;
350 
351     if (exynos_v4l2_querycap(fd, cap) == false) {
352         ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
353         if (0 < fd)
354             close(fd);
355         fd = 0;
356         return -1;
357     }
358     return fd;
359 }
360 
m_exynos_rotator_destroy(struct ROTATOR_HANDLE * rotator_handle)361 static bool m_exynos_rotator_destroy(
362     struct ROTATOR_HANDLE *rotator_handle)
363 {
364     if (rotator_handle->src.stream_on == true) {
365         if (exynos_v4l2_streamoff(rotator_handle->rotator_fd, rotator_handle->src.buf_type) < 0)
366             ALOGE("%s::exynos_v4l2_streamoff() fail", __func__);
367 
368         rotator_handle->src.stream_on = false;
369     }
370 
371     if (rotator_handle->dst.stream_on == true) {
372         if (exynos_v4l2_streamoff(rotator_handle->rotator_fd, rotator_handle->dst.buf_type) < 0)
373             ALOGE("%s::exynos_v4l2_streamoff() fail", __func__);
374 
375         rotator_handle->dst.stream_on = false;
376     }
377 
378     if (0 < rotator_handle->rotator_fd)
379         close(rotator_handle->rotator_fd);
380     rotator_handle->rotator_fd = 0;
381 
382     return true;
383 }
384 
m_exynos_rotator_find_and_trylock_and_create(struct ROTATOR_HANDLE * rotator_handle)385 bool m_exynos_rotator_find_and_trylock_and_create(
386     struct ROTATOR_HANDLE *rotator_handle)
387 {
388     int          i                 = 0;
389     bool         flag_find_new_rotator = false;
390     unsigned int total_sleep_time  = 0;
391 
392     do {
393         if (exynos_mutex_trylock(rotator_handle->obj_mutex) == true) {
394 
395             // destroy old one.
396             m_exynos_rotator_destroy(rotator_handle);
397 
398             // create new one.
399             rotator_handle->rotator_fd = m_exynos_rotator_create();
400             if (rotator_handle->rotator_fd < 0) {
401                 rotator_handle->rotator_fd = 0;
402                 exynos_mutex_unlock(rotator_handle->obj_mutex);
403                 continue;
404             }
405 
406             if (rotator_handle->cur_obj_mutex)
407                 exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
408 
409             rotator_handle->cur_obj_mutex = rotator_handle->obj_mutex;
410 
411             flag_find_new_rotator = true;
412             break;
413         }
414 
415         // waiting for another process doesn't use rotator.
416         // we need to make decision how to do.
417         if (flag_find_new_rotator == false) {
418             usleep(ROTATOR_WAITING_TIME_FOR_TRYLOCK);
419             total_sleep_time += ROTATOR_WAITING_TIME_FOR_TRYLOCK;
420             ALOGV("%s::waiting for anthere process doens't use rotator", __func__);
421         }
422 
423     } while(   flag_find_new_rotator == false
424             && total_sleep_time < MAX_ROTATOR_WAITING_TIME_FOR_TRYLOCK);
425 
426     if (flag_find_new_rotator == false)
427         ALOGE("%s::we don't have no available rotator.. fail", __func__);
428 
429     return flag_find_new_rotator;
430 }
431 
m_exynos_rotator_set_format(int fd,struct rotator_info * info,bool force)432 static bool m_exynos_rotator_set_format(
433     int                  fd,
434     struct rotator_info *info,
435     bool                 force)
436 {
437     struct v4l2_requestbuffers req_buf;
438     int                        plane_count;
439 
440     plane_count = m_rotator_get_plane_count(info->v4l2_colorformat);
441     if (plane_count < 0) {
442         ALOGE("%s::not supported v4l2_colorformat", __func__);
443         return false;
444     }
445 
446     if (force == false) {
447         // format
448         info->format.type = info->buf_type;
449         if (exynos_v4l2_g_fmt(fd, &info->format) < 0) {
450             ALOGE("%s::exynos_v4l2_g_fmt() fail type=%d", __func__, info->buf_type);
451             return false;
452         }
453 
454         if (info->width            != info->format.fmt.pix_mp.width ||
455             info->height           != info->format.fmt.pix_mp.height ||
456             info->v4l2_colorformat != info->format.fmt.pix_mp.pixelformat) {
457             ALOGV("%s::info is different..)", __func__);
458             goto set_hw;
459         }
460 
461         // crop
462         if (info->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
463         info->crop.type = info->buf_type;
464         if (exynos_v4l2_g_crop(fd, &info->crop) < 0) {
465             ALOGE("%s::exynos_v4l2_g_crop() fail", __func__);
466             return false;
467         }
468 
469         if (info->crop_left   != info->crop.c.left ||
470             info->crop_top    != info->crop.c.top ||
471             info->crop_width  != info->crop.c.width ||
472             info->crop_height != info->crop.c.height) {
473             ALOGV("%s::crop is different..", __func__);
474             goto set_hw;
475         }
476         }
477 
478         // rotation value;
479 
480         int value = 0;
481 
482         if (exynos_v4l2_g_ctrl(fd, V4L2_CID_ROTATE, &value) < 0) {
483             ALOGE("%s::exynos_v4l2_g_ctrl(V4L2_CID_ROTATE) fail");
484             return false;
485         }
486 
487         if (info->rotation != value) {
488             ALOGV("%s::rotation is different..", __func__);
489             goto set_hw;
490         }
491 
492         // skip s_fmt
493         ALOGV("%s::fmt, crop is same with old-one, so skip s_fmt crop..", __func__);
494         return true;
495     }
496 
497 set_hw:
498 
499     if (info->stream_on == true) {
500         if (exynos_v4l2_streamoff(fd, info->buf_type) < 0) {
501             ALOGE("%s::exynos_v4l2_streamoff() fail", __func__);
502             return false;
503         }
504         info->stream_on = false;
505     }
506 
507     if (exynos_v4l2_s_ctrl(fd, V4L2_CID_ROTATE, info->rotation) < 0) {
508         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_ROTATE) fail", __func__);
509         return false;
510     }
511 
512     info->format.fmt.pix_mp.width       = info->width;
513     info->format.fmt.pix_mp.height      = info->height;
514     info->format.fmt.pix_mp.pixelformat = info->v4l2_colorformat;
515     info->format.fmt.pix_mp.field       = V4L2_FIELD_ANY;
516     info->format.fmt.pix_mp.num_planes  = plane_count;
517 
518     if (exynos_v4l2_s_fmt(fd, &info->format) < 0) {
519         ALOGE("%s::exynos_v4l2_s_fmt() fail", __func__);
520         return false;
521     }
522 
523     if (info->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
524     info->crop.type     = info->buf_type;
525     info->crop.c.left   = info->crop_left;
526     info->crop.c.top    = info->crop_top;
527     info->crop.c.width  = info->crop_width;
528     info->crop.c.height = info->crop_height;
529 
530     if (exynos_v4l2_s_crop(fd, &info->crop) < 0) {
531         ALOGE("%s::exynos_v4l2_s_crop() fail", __func__);
532         return false;
533     }
534     }
535 
536     if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CACHEABLE, info->cacheable) < 0) {
537         ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
538         return false;
539     }
540 
541     req_buf.count  = 1;
542     req_buf.type   = info->buf_type;
543     req_buf.memory = V4L2_MEMORY_USERPTR;
544     if (exynos_v4l2_reqbufs(fd, &req_buf) < 0) {
545         ALOGE("%s::exynos_v4l2_reqbufs() fail", __func__);
546         return false;
547     }
548 
549     return true;
550 }
551 
m_exynos_rotator_set_addr(int fd,struct rotator_info * info)552 static bool m_exynos_rotator_set_addr(
553     int                  fd,
554     struct rotator_info *info)
555 {
556     unsigned int i;
557     unsigned int plane_size[NUM_OF_ROTATOR_PLANES];
558 
559     m_rotator_get_plane_size(plane_size,
560                          info->width,
561                          info->height,
562                          info->v4l2_colorformat);
563 
564     info->buffer.index    = 0;
565     info->buffer.type     = info->buf_type;
566     info->buffer.memory   = V4L2_MEMORY_USERPTR;
567     info->buffer.m.planes = info->planes;
568     info->buffer.length   = info->format.fmt.pix_mp.num_planes;
569 
570     for (i = 0; i < info->format.fmt.pix_mp.num_planes; i++) {
571         info->buffer.m.planes[i].m.userptr = (unsigned long)info->addr[i];
572         info->buffer.m.planes[i].length    = plane_size[i];
573         info->buffer.m.planes[i].bytesused = 0;
574     }
575 
576     if (exynos_v4l2_qbuf(fd, &info->buffer) < 0) {
577         ALOGE("%s::exynos_v4l2_qbuf() fail", __func__);
578         return false;
579     }
580 
581     return true;
582 }
583 
exynos_rotator_create(void)584 void *exynos_rotator_create(void)
585 {
586     int i     = 0;
587     int op_id = 0;
588     char mutex_name[32];
589 
590     struct ROTATOR_HANDLE *rotator_handle = (struct ROTATOR_HANDLE *)malloc(sizeof(struct ROTATOR_HANDLE));
591     if (rotator_handle == NULL) {
592         ALOGE("%s::malloc(struct ROTATOR_HANDLE) fail", __func__);
593         goto err;
594     }
595 
596     rotator_handle->rotator_fd = 0;
597     memset(&rotator_handle->src, 0, sizeof(struct rotator_info));
598     memset(&rotator_handle->dst, 0, sizeof(struct rotator_info));
599 
600     rotator_handle->src.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
601     rotator_handle->dst.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
602 
603     rotator_handle->op_mutex = NULL;
604     rotator_handle->obj_mutex = NULL;
605     rotator_handle->cur_obj_mutex = NULL;
606 
607     srand(time(NULL));
608     op_id = rand() % 1000000; // just make random id
609     sprintf(mutex_name, "%sOp%d", LOG_TAG, op_id);
610     rotator_handle->op_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_PRIVATE, mutex_name);
611     if (rotator_handle->op_mutex == NULL) {
612         ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
613         goto err;
614     }
615 
616     exynos_mutex_lock(rotator_handle->op_mutex);
617 
618     sprintf(mutex_name, "%sObject%d", LOG_TAG, i);
619 
620     rotator_handle->obj_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
621     if (rotator_handle->obj_mutex == NULL) {
622         ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
623         goto err;
624     }
625 
626     if (m_exynos_rotator_find_and_trylock_and_create(rotator_handle) == false) {
627         ALOGE("%s::m_exynos_rotator_find_and_trylock_and_create() fail", __func__);
628         goto err;
629     }
630 
631     exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
632     exynos_mutex_unlock(rotator_handle->op_mutex);
633 
634     return (void *)rotator_handle;
635 
636 err:
637     if (rotator_handle) {
638         m_exynos_rotator_destroy(rotator_handle);
639 
640         if (rotator_handle->cur_obj_mutex)
641             exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
642 
643         if ((rotator_handle->obj_mutex != NULL) &&
644             (exynos_mutex_get_created_status(rotator_handle->obj_mutex) == true)) {
645             if (exynos_mutex_destroy(rotator_handle->obj_mutex) == false)
646                 ALOGE("%s::exynos_mutex_destroy() fail", __func__);
647         }
648 
649         if (rotator_handle->op_mutex)
650             exynos_mutex_unlock(rotator_handle->op_mutex);
651 
652         free(rotator_handle);
653     }
654 
655     return NULL;
656 }
657 
exynos_rotator_destroy(void * handle)658 void exynos_rotator_destroy(
659     void *handle)
660 {
661     int i = 0;
662     struct ROTATOR_HANDLE *rotator_handle = (struct ROTATOR_HANDLE *)handle;
663 
664     if (handle == NULL) {
665         ALOGE("%s::handle == NULL() fail", __func__);
666         return;
667     }
668 
669     exynos_mutex_lock(rotator_handle->op_mutex);
670     exynos_mutex_lock(rotator_handle->cur_obj_mutex);
671 
672     m_exynos_rotator_destroy(rotator_handle);
673 
674     exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
675 
676     if ((rotator_handle->obj_mutex != NULL) &&
677         (exynos_mutex_get_created_status(rotator_handle->obj_mutex) == true)) {
678         if (exynos_mutex_destroy(rotator_handle->obj_mutex) == false)
679             ALOGE("%s::exynos_mutex_destroy() fail", __func__);
680     }
681 
682     exynos_mutex_unlock(rotator_handle->op_mutex);
683 
684     if (rotator_handle)
685         free(rotator_handle);
686 }
687 
exynos_rotator_set_src_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int v4l2_colorformat,unsigned int cacheable)688 int exynos_rotator_set_src_format(
689     void        *handle,
690     unsigned int width,
691     unsigned int height,
692     unsigned int crop_left,
693     unsigned int crop_top,
694     unsigned int crop_width,
695     unsigned int crop_height,
696     unsigned int v4l2_colorformat,
697     unsigned int cacheable)
698 {
699     struct ROTATOR_HANDLE *rotator_handle;
700     rotator_handle = (struct ROTATOR_HANDLE *)handle;
701 
702     if (handle == NULL) {
703         ALOGE("%s::handle == NULL() fail", __func__);
704         return -1;
705     }
706 
707     exynos_mutex_lock(rotator_handle->op_mutex);
708 
709     rotator_handle->src.width            = width;
710     rotator_handle->src.height           = height;
711     rotator_handle->src.crop_left        = crop_left;
712     rotator_handle->src.crop_top         = crop_top;
713     rotator_handle->src.crop_width       = crop_width;
714     rotator_handle->src.crop_height      = crop_height;
715     rotator_handle->src.v4l2_colorformat = v4l2_colorformat;
716     rotator_handle->src.cacheable        = cacheable;
717 
718     exynos_mutex_unlock(rotator_handle->op_mutex);
719 
720     return 0;
721 }
722 
exynos_rotator_set_dst_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int v4l2_colorformat,unsigned int cacheable)723 int exynos_rotator_set_dst_format(
724     void        *handle,
725     unsigned int width,
726     unsigned int height,
727     unsigned int crop_left,
728     unsigned int crop_top,
729     unsigned int v4l2_colorformat,
730     unsigned int cacheable)
731 {
732     struct ROTATOR_HANDLE *rotator_handle;
733     rotator_handle = (struct ROTATOR_HANDLE *)handle;
734 
735     if (handle == NULL) {
736         ALOGE("%s::handle == NULL() fail", __func__);
737         return -1;
738     }
739 
740     exynos_mutex_lock(rotator_handle->op_mutex);
741 
742     rotator_handle->dst.width            = width;
743     rotator_handle->dst.height           = height;
744     rotator_handle->dst.crop_left        = crop_left;
745     rotator_handle->dst.crop_top         = crop_top;
746     rotator_handle->dst.crop_width       = rotator_handle->src.crop_width;
747     rotator_handle->dst.crop_height      = rotator_handle->src.crop_height;
748     rotator_handle->dst.v4l2_colorformat = v4l2_colorformat;
749     rotator_handle->dst.cacheable        = cacheable;
750 
751     exynos_mutex_unlock(rotator_handle->op_mutex);
752 
753     return 0;
754 }
755 
exynos_rotator_set_rotation(void * handle,int rotation)756 int exynos_rotator_set_rotation(
757     void *handle,
758     int   rotation)
759 {
760     int ret = -1;
761     struct ROTATOR_HANDLE *rotator_handle;
762     rotator_handle = (struct ROTATOR_HANDLE *)handle;
763 
764     if (handle == NULL) {
765         ALOGE("%s::handle == NULL() fail", __func__);
766         return ret;
767     }
768 
769     exynos_mutex_lock(rotator_handle->op_mutex);
770 
771     int new_rotation = rotation % 360;
772 
773     if (new_rotation % 90 != 0) {
774         ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__, rotation);
775         goto done;
776     }
777 
778     if(new_rotation < 0)
779         new_rotation = -new_rotation;
780 
781     rotator_handle->src.rotation = new_rotation;
782     rotator_handle->dst.rotation = new_rotation;
783 
784     ret = 0;
785 done:
786     exynos_mutex_unlock(rotator_handle->op_mutex);
787 
788     return ret;
789 }
790 
exynos_rotator_set_src_addr(void * handle,void * addr[3])791 int exynos_rotator_set_src_addr(
792     void *handle,
793     void *addr[3])
794 {
795     struct ROTATOR_HANDLE *rotator_handle;
796     rotator_handle = (struct ROTATOR_HANDLE *)handle;
797 
798     if (handle == NULL) {
799         ALOGE("%s::handle == NULL() fail", __func__);
800         return -1;
801     }
802 
803     exynos_mutex_lock(rotator_handle->op_mutex);
804 
805     rotator_handle->src.addr[0] = addr[0];
806     rotator_handle->src.addr[1] = addr[1];
807     rotator_handle->src.addr[2] = addr[2];
808 
809     exynos_mutex_unlock(rotator_handle->op_mutex);
810 
811     return 0;
812 }
813 
exynos_rotator_set_dst_addr(void * handle,void * addr[3])814 int exynos_rotator_set_dst_addr(
815     void *handle,
816     void *addr[3])
817 {
818     struct ROTATOR_HANDLE *rotator_handle;
819     rotator_handle = (struct ROTATOR_HANDLE *)handle;
820 
821     if (handle == NULL) {
822         ALOGE("%s::handle == NULL() fail", __func__);
823         return -1;
824     }
825 
826     exynos_mutex_lock(rotator_handle->op_mutex);
827 
828     rotator_handle->dst.addr[0] = addr[0];
829     rotator_handle->dst.addr[1] = addr[1];
830     rotator_handle->dst.addr[2] = addr[2];
831 
832     exynos_mutex_unlock(rotator_handle->op_mutex);
833 
834     return 0;
835 }
836 
exynos_rotator_convert(void * handle)837 int exynos_rotator_convert(
838     void *handle)
839 {
840     struct ROTATOR_HANDLE *rotator_handle;
841     int ret    = -1;
842     int i      = 0;
843     rotator_handle = (struct ROTATOR_HANDLE *)handle;
844 
845     if (handle == NULL) {
846         ALOGE("%s::handle == NULL() fail", __func__);
847         return -1;
848     }
849 
850     char mutex_name[32];
851     bool flag_new_rotator = false;
852 
853     exynos_mutex_lock(rotator_handle->op_mutex);
854 
855     if (exynos_mutex_trylock(rotator_handle->cur_obj_mutex) == false) {
856         if (m_exynos_rotator_find_and_trylock_and_create(rotator_handle) == false) {
857             ALOGE("%s::m_exynos_rotator_find_and_trylock_and_create() fail", __func__);
858             goto done;
859         }
860         flag_new_rotator = true;
861     }
862 
863     if (m_exynos_rotator_check_src_size(&rotator_handle->src.width, &rotator_handle->src.width,
864                                     &rotator_handle->src.crop_left, &rotator_handle->src.crop_top,
865                                     &rotator_handle->src.crop_width, &rotator_handle->src.crop_height,
866                                     rotator_handle->src.v4l2_colorformat) == false) {
867         ALOGE("%s::m_exynos_rotator_check_size(src) fail", __func__);
868         goto done;
869     }
870 
871     if (m_exynos_rotator_check_dst_size(&rotator_handle->dst.width, &rotator_handle->dst.height,
872                                     &rotator_handle->dst.crop_left, &rotator_handle->dst.crop_top,
873                                     &rotator_handle->dst.crop_width, &rotator_handle->dst.crop_height,
874                                     rotator_handle->dst.v4l2_colorformat,
875                                     rotator_handle->dst.rotation) == false) {
876         ALOGE("%s::m_exynos_rotator_check_size(dst) fail", __func__);
877         goto done;
878     }
879 
880     if (m_exynos_rotator_set_format(rotator_handle->rotator_fd, &rotator_handle->src, flag_new_rotator) == false) {
881         ALOGE("%s::m_exynos_rotator_set_format(src) fail", __func__);
882         goto done;
883     }
884 
885     if (m_exynos_rotator_set_format(rotator_handle->rotator_fd, &rotator_handle->dst, flag_new_rotator) == false) {
886         ALOGE("%s::m_exynos_rotator_set_format(dst) fail", __func__);
887         goto done;
888     }
889 
890     if (m_exynos_rotator_set_addr(rotator_handle->rotator_fd, &rotator_handle->src) == false) {
891         ALOGE("%s::m_exynos_rotator_set_addr(src) fail", __func__);
892         goto done;
893     }
894 
895     if (m_exynos_rotator_set_addr(rotator_handle->rotator_fd, &rotator_handle->dst) == false) {
896         ALOGE("%s::m_exynos_rotator_set_addr(dst) fail", __func__);
897         goto done;
898     }
899 
900     if (rotator_handle->src.stream_on == false) {
901         if (exynos_v4l2_streamon(rotator_handle->rotator_fd, rotator_handle->src.buf_type) < 0) {
902             ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
903             goto done;
904         }
905         rotator_handle->src.stream_on = true;
906     }
907 
908     if (rotator_handle->dst.stream_on == false) {
909         if (exynos_v4l2_streamon(rotator_handle->rotator_fd, rotator_handle->dst.buf_type) < 0) {
910             ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
911             goto done;
912         }
913         rotator_handle->dst.stream_on = true;
914     }
915 
916     if (exynos_v4l2_dqbuf(rotator_handle->rotator_fd, &rotator_handle->src.buffer) < 0) {
917         ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__);
918         goto done;
919     }
920 
921     if (exynos_v4l2_dqbuf(rotator_handle->rotator_fd, &rotator_handle->dst.buffer) < 0) {
922         ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__);
923         goto done;
924     }
925 
926     if (rotator_handle->src.stream_on == true) {
927         if (exynos_v4l2_streamoff(rotator_handle->rotator_fd, rotator_handle->src.buf_type) < 0) {
928             ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
929             goto done;
930         }
931         rotator_handle->src.stream_on = false;
932     }
933 
934     if (rotator_handle->dst.stream_on == true) {
935         if (exynos_v4l2_streamoff(rotator_handle->rotator_fd, rotator_handle->dst.buf_type) < 0) {
936             ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
937             goto done;
938         }
939         rotator_handle->dst.stream_on = false;
940     }
941 
942     ret = 0;
943 
944 done:
945     exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
946     exynos_mutex_unlock(rotator_handle->op_mutex);
947 
948     return ret;
949 }
950 
exynos_rotator_connect(void * handle,void * hw)951 int exynos_rotator_connect(
952     void *handle,
953     void *hw)
954 {
955     struct ROTATOR_HANDLE *rotator_handle;
956     int ret    = -1;
957     rotator_handle = (struct ROTATOR_HANDLE *)handle;
958 
959     if (handle == NULL) {
960         ALOGE("%s::handle == NULL() fail", __func__);
961         return -1;
962     }
963 
964     exynos_mutex_lock(rotator_handle->op_mutex);
965 
966     if (exynos_mutex_trylock(rotator_handle->cur_obj_mutex) == false) {
967         if (m_exynos_rotator_find_and_trylock_and_create(rotator_handle) == false) {
968             ALOGE("%s::m_exynos_rotator_find_and_trylock_and_create() fail", __func__);
969             goto done;
970         }
971     }
972 
973     ret = 0;
974 
975 done:
976     exynos_mutex_unlock(rotator_handle->op_mutex);
977 
978     return ret;
979 }
980 
exynos_rotator_disconnect(void * handle,void * hw)981 int exynos_rotator_disconnect(
982     void *handle,
983     void *hw)
984 {
985     struct ROTATOR_HANDLE *rotator_handle;
986     rotator_handle = (struct ROTATOR_HANDLE *)handle;
987 
988     if (handle == NULL) {
989         ALOGE("%s::handle == NULL() fail", __func__);
990         return -1;
991     }
992 
993     exynos_mutex_lock(rotator_handle->op_mutex);
994 
995     exynos_mutex_unlock(rotator_handle->cur_obj_mutex);
996     exynos_mutex_unlock(rotator_handle->op_mutex);
997 
998     return 0;
999 }
1000