blob: 24e74fc2d763ea2e10aaa4b065f4ef9492a81694 [file] [log] [blame]
Paul Kocialkowskib31c4462013-09-01 19:22:36 +02001/*
2 * Copyright (C) 2013 Paul Kocialkowski
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <fcntl.h>
19#include <unistd.h>
20#include <errno.h>
21#include <malloc.h>
22#include <poll.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <sys/time.h>
26#include <sys/mman.h>
27#include <sys/ioctl.h>
28
29#include <asm/types.h>
30
31#define LOG_TAG "exynos_jpeg"
32#include <utils/Log.h>
33
34#include "exynos_camera.h"
35
36#ifdef EXYNOS_JPEG_HW
37int exynos_jpeg_start(struct exynos_camera *exynos_camera,
38 struct exynos_jpeg *jpeg)
39{
40 struct jpeg_config config;
41 struct jpeg_buf *buffer_in;
42 struct jpeg_buf *buffer_out;
43 camera_memory_t *memory = NULL;
44#ifdef EXYNOS_ION
45 int memory_ion_fd = -1;
46#endif
47 int address;
48 int fd = -1;
49 int rc;
50
51 if (exynos_camera == NULL || jpeg == NULL)
52 return -EINVAL;
53
54 ALOGD("%s()", __func__);
55
56 if (jpeg->enabled) {
57 ALOGE("Jpeg was already started");
58 return -1;
59 }
60
61 buffer_in = &jpeg->buffer_in;
62 buffer_out = &jpeg->buffer_out;
63
64#ifdef EXYNOS_ION
65 jpeg->memory_in_ion_fd = -1;
66 jpeg->memory_out_ion_fd = -1;
67#endif
68
69 fd = jpeghal_enc_init();
70 if (fd < 0) {
71 ALOGE("%s: Unable to init jpeg encoder", __func__);
72 goto error;
73 }
74
75 jpeg->fd = fd;
76
77 memset(&config, 0, sizeof(config));
78 config.mode = JPEG_ENCODE;
79 config.width = jpeg->width;
80 config.height = jpeg->height;
81 config.num_planes = 1;
82 config.pix.enc_fmt.in_fmt = jpeg->format;
83 config.pix.enc_fmt.out_fmt = V4L2_PIX_FMT_JPEG_420;
84
85 if (jpeg->quality >= 90)
86 config.enc_qual = QUALITY_LEVEL_1;
87 else if (jpeg->quality >= 80)
88 config.enc_qual = QUALITY_LEVEL_2;
89 else if (jpeg->quality >= 70)
90 config.enc_qual = QUALITY_LEVEL_3;
91 else
92 config.enc_qual = QUALITY_LEVEL_4;
93
94 rc = jpeghal_enc_setconfig(fd, &config);
95 if (rc < 0) {
96 ALOGE("%s: Unable to set jpeg config", __func__);
97 goto error;
98 }
99
100 rc = jpeghal_s_ctrl(fd, V4L2_CID_CACHEABLE, 1);
101 if (rc < 0) {
102 ALOGE("%s: Unable to set cacheable control", __func__);
103 goto error;
104 }
105
106 memset(buffer_in, 0, sizeof(struct jpeg_buf));
107 buffer_in->memory = V4L2_MEMORY_MMAP;
108 buffer_in->num_planes = 1;
109
110 memset(buffer_out, 0, sizeof(struct jpeg_buf));
111 buffer_out->memory = V4L2_MEMORY_MMAP;
112 buffer_out->num_planes = 1;
113
114 rc = jpeghal_set_inbuf(fd, buffer_in);
115 if (rc < 0) {
116#ifdef EXYNOS_ION
117 // Input
118
119 buffer_in->memory = V4L2_MEMORY_USERPTR;
120 buffer_in->length[0] = exynos_camera_buffer_length(jpeg->width, jpeg->height, jpeg->format);
121
122 memory_ion_fd = exynos_ion_alloc(exynos_camera, buffer_in->length[0]);
123 if (memory_ion_fd < 0) {
124 ALOGE("%s: Unable to alloc input ION memory", __func__);
125 goto error;
126 }
127
128 address = exynos_ion_phys(exynos_camera, memory_ion_fd);
129
130 if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) {
131 memory = exynos_camera->callbacks.request_memory(memory_ion_fd, buffer_in->length[0], 1, exynos_camera->callbacks.user);
132 if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) {
133 ALOGE("%s: Unable to request memory", __func__);
134 goto error;
135 }
136 } else {
137 ALOGE("%s: No memory request function!", __func__);
138 goto error;
139 }
140
141 jpeg->memory_in = memory;
142 jpeg->memory_in_pointer = memory->data;
143 jpeg->memory_in_ion_fd = memory_ion_fd;
144 buffer_in->start[0] = (void *) address;
145
146 rc = jpeghal_set_inbuf(fd, buffer_in);
147 if (rc < 0) {
148 ALOGE("%s: Unable to set input buffer", __func__);
149 goto error;
150 }
151
152 // Output
153
154 buffer_out->memory = V4L2_MEMORY_USERPTR;
155 buffer_out->length[0] = jpeg->width * jpeg->height * 4;
156
157 memory_ion_fd = exynos_ion_alloc(exynos_camera, buffer_out->length[0]);
158 if (memory_ion_fd < 0) {
159 ALOGE("%s: Unable to alloc output ION memory", __func__);
160 goto error;
161 }
162
163 address = exynos_ion_phys(exynos_camera, memory_ion_fd);
164
165 if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) {
166 memory = exynos_camera->callbacks.request_memory(memory_ion_fd, buffer_out->length[0], 1, exynos_camera->callbacks.user);
167 if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) {
168 ALOGE("%s: Unable to request memory", __func__);
169 goto error;
170 }
171 } else {
172 ALOGE("%s: No memory request function!", __func__);
173 goto error;
174 }
175
176 jpeg->memory_out = memory;
177 jpeg->memory_out_pointer = memory->data;
178 jpeg->memory_out_ion_fd = memory_ion_fd;
179 buffer_out->start[0] = (void *) address;
180#else
181 ALOGE("%s: Unable to set input buffer", __func__);
182 goto error;
183#endif
184 } else {
185 jpeg->memory_in_pointer = buffer_in->start[0];
186 jpeg->memory_out_pointer = buffer_out->start[0];
187 }
188
189 rc = jpeghal_set_outbuf(fd, buffer_out);
190 if (rc < 0) {
191 ALOGE("%s: Unable to set output buffer", __func__);
192 goto error;
193 }
194
195 jpeg->enabled = 1;
196
197 rc = 0;
198 goto complete;
199
200error:
201 if (fd >= 0) {
202 // Avoid releasing unrequested mmap buffers
203
204 if (buffer_in->memory == 0)
205 buffer_in->memory = V4L2_MEMORY_USERPTR;
206
207 if (buffer_out->memory == 0)
208 buffer_out->memory = V4L2_MEMORY_USERPTR;
209
210 jpeghal_deinit(fd, buffer_in, buffer_out);
211 jpeg->fd = -1;
212 }
213
214 if (jpeg->memory_in != NULL && jpeg->memory_in->release != NULL) {
215 jpeg->memory_in->release(jpeg->memory_in);
216 jpeg->memory_in = NULL;
217#ifdef EXYNOS_ION
218 if (jpeg->memory_in_ion_fd >= 0) {
219 exynos_ion_free(exynos_camera, jpeg->memory_in_ion_fd);
220 jpeg->memory_in_ion_fd = -1;
221 }
222#endif
223 }
224
225 if (jpeg->memory_out != NULL && jpeg->memory_out->release != NULL) {
226 jpeg->memory_out->release(jpeg->memory_out);
227 jpeg->memory_out = NULL;
228
229#ifdef EXYNOS_ION
230 if (jpeg->memory_out_ion_fd >= 0) {
231 exynos_ion_free(exynos_camera, jpeg->memory_out_ion_fd);
232 jpeg->memory_out_ion_fd = -1;
233 }
234#endif
235 }
236
237 rc = -1;
238
239complete:
240 return rc;
241}
242
243void exynos_jpeg_stop(struct exynos_camera *exynos_camera,
244 struct exynos_jpeg *jpeg)
245{
246 struct jpeg_buf *buffer_in;
247 struct jpeg_buf *buffer_out;
248 int fd = -1;
249 int rc;
250
251 if (exynos_camera == NULL || jpeg == NULL)
252 return;
253
254 ALOGD("%s()", __func__);
255
256 if (!jpeg->enabled) {
257 ALOGE("Jpeg was already stopped");
258 return;
259 }
260
261 buffer_in = &jpeg->buffer_in;
262 buffer_out = &jpeg->buffer_out;
263
264 fd = jpeg->fd;
265
266 if (fd >= 0) {
267 jpeghal_deinit(fd, buffer_in, buffer_out);
268 jpeg->fd = -1;
269 }
270
271 if (jpeg->memory_in != NULL && jpeg->memory_in->release != NULL) {
272 jpeg->memory_in->release(jpeg->memory_in);
273 jpeg->memory_in = NULL;
274#ifdef EXYNOS_ION
275 if (jpeg->memory_in_ion_fd >= 0) {
276 exynos_ion_free(exynos_camera, jpeg->memory_in_ion_fd);
277 jpeg->memory_in_ion_fd = -1;
278 }
279#endif
280 }
281
282 if (jpeg->memory_out != NULL && jpeg->memory_out->release != NULL) {
283 jpeg->memory_out->release(jpeg->memory_out);
284 jpeg->memory_out = NULL;
285
286#ifdef EXYNOS_ION
287 if (jpeg->memory_out_ion_fd >= 0) {
288 exynos_ion_free(exynos_camera, jpeg->memory_out_ion_fd);
289 jpeg->memory_out_ion_fd = -1;
290 }
291#endif
292 }
293
294 jpeg->enabled = 0;
295}
296
297int exynos_jpeg(struct exynos_camera *exynos_camera, struct exynos_jpeg *jpeg)
298{
299 struct jpeg_buf *buffer_in;
300 struct jpeg_buf *buffer_out;
301 int memory_size;
302 int fd = -1;
303 int rc;
304
305 if (exynos_camera == NULL || jpeg == NULL)
306 return -EINVAL;
307
308 ALOGD("%s()", __func__);
309
310 if (!jpeg->enabled) {
311 ALOGE("Jpeg was not started");
312 return -1;
313 }
314
315 buffer_in = &jpeg->buffer_in;
316 buffer_out = &jpeg->buffer_out;
317
318 fd = jpeg->fd;
319 if (fd < 0) {
320 ALOGE("%s: Invalid jpeg fd", __func__);
321 goto error;
322 }
323
324#ifdef EXYNOS_ION
325 if (jpeg->memory_in != NULL && jpeg->memory_in_ion_fd >= 0) {
326 rc = exynos_ion_msync(exynos_camera, jpeg->memory_in_ion_fd, 0, buffer_in->length[0]);
327 if (rc < 0) {
328 ALOGE("%s: Unable to sync ION memory", __func__);
329 goto error;
330 }
331 }
332#endif
333
334 rc = jpeghal_enc_exe(fd, buffer_in, buffer_out);
335 if (rc < 0) {
336 ALOGE("%s: Unable to encode jpeg", __func__);
337 goto error;
338 }
339
340 memory_size = jpeghal_g_ctrl(fd, V4L2_CID_CAM_JPEG_ENCODEDSIZE);
341 if (memory_size <= 0) {
342 ALOGE("%s: Unable to get jpeg size", __func__);
343 goto error;
344 }
345
346 jpeg->memory_out_size = memory_size;
347
348#ifdef EXYNOS_ION
349 if (jpeg->memory_out != NULL && jpeg->memory_out_ion_fd >= 0) {
350 rc = exynos_ion_msync(exynos_camera, jpeg->memory_out_ion_fd, 0, memory_size);
351 if (rc < 0) {
352 ALOGE("%s: Unable to sync ION memory", __func__);
353 goto error;
354 }
355 }
356#endif
357
358 rc = 0;
359 goto complete;
360
361error:
362 if (fd >= 0) {
363 // Avoid releasing unrequested mmap buffers
364
365 if (buffer_in->memory == 0)
366 buffer_in->memory = V4L2_MEMORY_USERPTR;
367
368 if (buffer_out->memory == 0)
369 buffer_out->memory = V4L2_MEMORY_USERPTR;
370
371 jpeghal_deinit(fd, buffer_in, buffer_out);
372 jpeg->fd = -1;
373 }
374
375 if (jpeg->memory_in != NULL && jpeg->memory_in->release != NULL) {
376 jpeg->memory_in->release(jpeg->memory_in);
377 jpeg->memory_in = NULL;
378
379#ifdef EXYNOS_ION
380 if (jpeg->memory_in_ion_fd >= 0) {
381 exynos_ion_free(exynos_camera, jpeg->memory_in_ion_fd);
382 jpeg->memory_in_ion_fd = -1;
383 }
384#endif
385 }
386
387 if (jpeg->memory_out != NULL && jpeg->memory_out->release != NULL) {
388 jpeg->memory_out->release(jpeg->memory_out);
389 jpeg->memory_out = NULL;
390
391#ifdef EXYNOS_ION
392 if (jpeg->memory_out_ion_fd >= 0) {
393 exynos_ion_free(exynos_camera, jpeg->memory_out_ion_fd);
394 jpeg->memory_out_ion_fd = -1;
395 }
396#endif
397 }
398
399 rc = -1;
400
401complete:
402 return rc;
403}
404#endif