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