2 * Copyright (C) 2014 The Android Open Source Project
3 * Copyright@ Samsung Electronics Co. LTD
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * \file libscaler-m2m1shot.cpp
20 * \brief source file for Scaler HAL
21 * \author Cho KyongHo <pullip.cho@samsung.com>
24 * <b>Revision History: </b>
25 * - 2014.05.08 : Cho KyongHo (pullip.cho@samsung.com) \n
31 #include <sys/ioctl.h>
33 #include <videodev2.h>
35 #include <exynos_scaler.h>
37 #include "libscaler-common.h"
38 #include "libscaler-m2m1shot.h"
42 const char dev_base_name
[] = "/dev/m2m1shot_scaler";
43 #define DEVBASE_NAME_LEN 20
51 const static PixFormat g_pixfmt_table
[] = {
52 {V4L2_PIX_FMT_RGB32
, 1, {32, 0, 0}, },
53 {V4L2_PIX_FMT_BGR32
, 1, {32, 0, 0}, },
54 {V4L2_PIX_FMT_RGB565
, 1, {16, 0, 0}, },
55 {V4L2_PIX_FMT_RGB555X
, 1, {16, 0, 0}, },
56 {V4L2_PIX_FMT_RGB444
, 1, {16, 0, 0}, },
57 {V4L2_PIX_FMT_YUYV
, 1, {16, 0, 0}, },
58 {V4L2_PIX_FMT_YVYU
, 1, {16, 0, 0}, },
59 {V4L2_PIX_FMT_UYVY
, 1, {16, 0, 0}, },
60 {V4L2_PIX_FMT_NV16
, 1, {16, 0, 0}, },
61 {V4L2_PIX_FMT_NV61
, 1, {16, 0, 0}, },
62 {V4L2_PIX_FMT_YUV420
, 1, {12, 0, 0}, },
63 {V4L2_PIX_FMT_YVU420
, 1, {12, 0, 0}, },
64 {V4L2_PIX_FMT_NV12M
, 2, {8, 4, 0}, },
65 {V4L2_PIX_FMT_NV21M
, 2, {8, 4, 0}, },
66 {v4l2_fourcc('V', 'M', '1', '2'), 2, {8, 4, 0}, },
67 {V4L2_PIX_FMT_NV12
, 1, {12, 0, 0}, },
68 {V4L2_PIX_FMT_NV21
, 1, {12, 0, 0}, },
69 {v4l2_fourcc('N', 'M', '2', '1'), 2, {8, 4, 0}, },
70 {V4L2_PIX_FMT_YUV420M
, 3, {8, 2, 2}, },
71 {V4L2_PIX_FMT_YVU420M
, 3, {8, 2, 2}, },
72 {V4L2_PIX_FMT_NV24
, 1, {24, 0, 0}, },
73 {V4L2_PIX_FMT_NV42
, 1, {24, 0, 0}, },
77 CScalerM2M1SHOT::CScalerM2M1SHOT(int devid
, int drm
) : m_iFD(-1)
79 char devname
[DEVBASE_NAME_LEN
+ 2]; // basenamelen + id + null
81 if ((devid
< 0) || (devid
> 4)) { // instance number must be between 0 ~ 3
82 SC_LOGE("Invalid device instance ID %d", devid
);
86 strncpy(devname
, dev_base_name
, DEVBASE_NAME_LEN
);
87 devname
[DEVBASE_NAME_LEN
] = devid
+ '0';
88 devname
[DEVBASE_NAME_LEN
+ 1] = '\0';
90 memset(&m_task
, 0, sizeof(m_task
));
92 m_iFD
= open(devname
, O_RDWR
);
94 SC_LOGERR("Failed to open '%s'", devname
);
96 // default 3 planes not to miss any buffer address
97 m_task
.buf_out
.num_planes
= 3;
98 m_task
.buf_cap
.num_planes
= 3;
102 CScalerM2M1SHOT::~CScalerM2M1SHOT()
108 bool CScalerM2M1SHOT::CScalerM2M1SHOT::Run()
112 ret
= ioctl(m_iFD
, M2M1SHOT_IOC_PROCESS
, &m_task
);
114 SC_LOGERR("Failed to process the given M2M1SHOT task");
121 bool CScalerM2M1SHOT::SetFormat(m2m1shot_pix_format
&fmt
, m2m1shot_buffer
&buf
,
122 unsigned int width
, unsigned int height
, unsigned int v4l2_fmt
) {
123 const PixFormat
*pixfmt
= NULL
;
129 for (size_t i
= 0; i
< ARRSIZE(g_pixfmt_table
); i
++) {
130 if (g_pixfmt_table
[i
].pixfmt
== v4l2_fmt
) {
131 pixfmt
= &g_pixfmt_table
[i
];
137 SC_LOGE("Format %#x is not supported", v4l2_fmt
);
141 for (int i
= 0; i
< pixfmt
->planes
; i
++) {
142 if (((pixfmt
->bit_pp
[i
] * width
) % 8) != 0) {
143 SC_LOGE("Plane %d of format %#x must have even width", i
, v4l2_fmt
);
146 buf
.plane
[i
].len
= (pixfmt
->bit_pp
[i
] * width
* height
) / 8;
149 buf
.num_planes
= pixfmt
->planes
;
154 bool CScalerM2M1SHOT::SetCrop(m2m1shot_pix_format
&fmt
,
155 unsigned int l
, unsigned int t
, unsigned int w
, unsigned int h
) {
156 if (fmt
.width
<= l
) {
157 SC_LOGE("crop left %d is larger than image width %d", l
, fmt
.width
);
160 if (fmt
.height
<= t
) {
161 SC_LOGE("crop top %d is larger than image height %d", t
, fmt
.height
);
164 if (fmt
.width
< (l
+ w
)) {
165 SC_LOGE("crop width %d@%d exceeds image width %d", w
, l
, fmt
.width
);
168 if (fmt
.height
< (t
+ h
)) {
169 SC_LOGE("crop height %d@%d exceeds image height %d", h
, t
, fmt
.height
);
181 bool CScalerM2M1SHOT::SetAddr(
182 m2m1shot_buffer
&buf
, void *addr
[SC_NUM_OF_PLANES
], int mem_type
) {
183 if (mem_type
== V4L2_MEMORY_DMABUF
) {
184 buf
.type
= M2M1SHOT_BUFFER_DMABUF
;
185 for (int i
= 0; i
< buf
.num_planes
; i
++)
186 buf
.plane
[i
].fd
= reinterpret_cast<int>(addr
[i
]);
187 } else if (mem_type
== V4L2_MEMORY_USERPTR
) {
188 buf
.type
= M2M1SHOT_BUFFER_USERPTR
;
189 for (int i
= 0; i
< buf
.num_planes
; i
++)
190 buf
.plane
[i
].userptr
= reinterpret_cast<unsigned long>(addr
[i
]);
192 SC_LOGE("Unknown buffer type %d", mem_type
);
199 bool CScalerM2M1SHOT::SetRotate(int rot
, int hflip
, int vflip
) {
200 if ((rot
% 90) != 0) {
201 SC_LOGE("Rotation degree %d must be multiple of 90", rot
);
209 m_task
.op
.rotate
= rot
;
210 m_task
.op
.op
&= ~(M2M1SHOT_OP_FLIP_HORI
| M2M1SHOT_OP_FLIP_VIRT
);
212 m_task
.op
.op
|= M2M1SHOT_OP_FLIP_HORI
;
214 m_task
.op
.op
|= M2M1SHOT_OP_FLIP_VIRT
;