import exynos 7570 bsp
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / libscaler / libscaler-m2m1shot.cpp
1 /*
2 * Copyright (C) 2014 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 libscaler-m2m1shot.cpp
20 * \brief source file for Scaler HAL
21 * \author Cho KyongHo <pullip.cho@samsung.com>
22 * \date 2014/05/08
23 *
24 * <b>Revision History: </b>
25 * - 2014.05.08 : Cho KyongHo (pullip.cho@samsung.com) \n
26 * Create
27 */
28 #include <cstring>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <sys/ioctl.h>
32
33 #include <videodev2.h>
34
35 #include <exynos_scaler.h>
36
37 #include "libscaler-common.h"
38 #include "libscaler-m2m1shot.h"
39
40 using namespace std;
41
42 const char dev_base_name[] = "/dev/m2m1shot_scaler";
43 #define DEVBASE_NAME_LEN 20
44
45 struct PixFormat {
46 unsigned int pixfmt;
47 char planes;
48 char bit_pp[3];
49 };
50
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}, },
74 };
75
76
77 CScalerM2M1SHOT::CScalerM2M1SHOT(int devid, int drm) : m_iFD(-1)
78 {
79 char devname[DEVBASE_NAME_LEN + 2]; // basenamelen + id + null
80
81 if ((devid < 0) || (devid > 4)) { // instance number must be between 0 ~ 3
82 SC_LOGE("Invalid device instance ID %d", devid);
83 return;
84 }
85
86 strncpy(devname, dev_base_name, DEVBASE_NAME_LEN);
87 devname[DEVBASE_NAME_LEN] = devid + '0';
88 devname[DEVBASE_NAME_LEN + 1] = '\0';
89
90 memset(&m_task, 0, sizeof(m_task));
91
92 m_iFD = open(devname, O_RDWR);
93 if (m_iFD < 0) {
94 SC_LOGERR("Failed to open '%s'", devname);
95 } else {
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;
99 }
100 }
101
102 CScalerM2M1SHOT::~CScalerM2M1SHOT()
103 {
104 if (m_iFD >= 0)
105 close(m_iFD);
106 }
107
108 bool CScalerM2M1SHOT::CScalerM2M1SHOT::Run()
109 {
110 int ret;
111
112 ret = ioctl(m_iFD, M2M1SHOT_IOC_PROCESS, &m_task);
113 if (ret < 0) {
114 SC_LOGERR("Failed to process the given M2M1SHOT task");
115 return false;
116 }
117
118 return true;
119 }
120
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;
124
125 fmt.width = width;
126 fmt.height = height;
127 fmt.fmt = v4l2_fmt;
128
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];
132 break;
133 }
134 }
135
136 if (!pixfmt) {
137 SC_LOGE("Format %#x is not supported", v4l2_fmt);
138 return false;
139 }
140
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);
144 return false;
145 }
146 buf.plane[i].len = (pixfmt->bit_pp[i] * width * height) / 8;
147 }
148
149 buf.num_planes = pixfmt->planes;
150
151 return true;
152 }
153
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);
158 return false;
159 }
160 if (fmt.height <= t) {
161 SC_LOGE("crop top %d is larger than image height %d", t, fmt.height);
162 return false;
163 }
164 if (fmt.width < (l + w)) {
165 SC_LOGE("crop width %d@%d exceeds image width %d", w, l, fmt.width);
166 return false;
167 }
168 if (fmt.height < (t + h)) {
169 SC_LOGE("crop height %d@%d exceeds image height %d", h, t, fmt.height);
170 return false;
171 }
172
173 fmt.crop.left = l;
174 fmt.crop.top = t;
175 fmt.crop.width = w;
176 fmt.crop.height = h;
177
178 return true;
179 }
180
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]);
191 } else {
192 SC_LOGE("Unknown buffer type %d", mem_type);
193 return false;
194 }
195
196 return true;
197 }
198
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);
202 return false;
203 }
204
205 rot = rot % 360;
206 if (rot < 0)
207 rot = 360 + rot;
208
209 m_task.op.rotate = rot;
210 m_task.op.op &= ~(M2M1SHOT_OP_FLIP_HORI | M2M1SHOT_OP_FLIP_VIRT);
211 if (hflip)
212 m_task.op.op |= M2M1SHOT_OP_FLIP_HORI;
213 if (vflip)
214 m_task.op.op |= M2M1SHOT_OP_FLIP_VIRT;
215
216 return true;
217 }