blob: 3e3d94dd03f86ef8fbe66a8542fdace0e56b01b5 [file] [log] [blame]
Mauro Carvalho Chehab2c3fb082012-08-14 17:31:16 -03001/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002 *
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03004 * http://www.samsung.com
5 *
6 * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03007 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03008 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/clk.h>
15#include <linux/err.h>
16#include <linux/gfp.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -030021#include <linux/of.h>
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030022#include <linux/platform_device.h>
23#include <linux/pm_runtime.h>
24#include <linux/slab.h>
25#include <linux/spinlock.h>
26#include <linux/string.h>
27#include <media/v4l2-mem2mem.h>
28#include <media/v4l2-ioctl.h>
29#include <media/videobuf2-core.h>
30#include <media/videobuf2-dma-contig.h>
31
32#include "jpeg-core.h"
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -030033#include "jpeg-hw-s5p.h"
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030034#include "jpeg-hw-exynos4.h"
Jacek Anaszewski3246fda2014-07-11 12:19:42 -030035#include "jpeg-hw-exynos3250.h"
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030036#include "jpeg-regs.h"
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030037
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030038static struct s5p_jpeg_fmt sjpeg_formats[] = {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030039 {
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -030040 .name = "JPEG JFIF",
41 .fourcc = V4L2_PIX_FMT_JPEG,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030042 .flags = SJPEG_FMT_FLAG_ENC_CAPTURE |
43 SJPEG_FMT_FLAG_DEC_OUTPUT |
44 SJPEG_FMT_FLAG_S5P |
Jacek Anaszewski3246fda2014-07-11 12:19:42 -030045 SJPEG_FMT_FLAG_EXYNOS3250 |
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030046 SJPEG_FMT_FLAG_EXYNOS4,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030047 },
48 {
49 .name = "YUV 4:2:2 packed, YCbYCr",
50 .fourcc = V4L2_PIX_FMT_YUYV,
51 .depth = 16,
52 .colplanes = 1,
53 .h_align = 4,
54 .v_align = 3,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030055 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
56 SJPEG_FMT_FLAG_DEC_CAPTURE |
57 SJPEG_FMT_FLAG_S5P |
58 SJPEG_FMT_NON_RGB,
59 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030060 },
61 {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030062 .name = "YUV 4:2:2 packed, YCbYCr",
63 .fourcc = V4L2_PIX_FMT_YUYV,
64 .depth = 16,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030065 .colplanes = 1,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030066 .h_align = 1,
67 .v_align = 0,
68 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
69 SJPEG_FMT_FLAG_DEC_CAPTURE |
70 SJPEG_FMT_FLAG_EXYNOS4 |
71 SJPEG_FMT_NON_RGB,
72 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
73 },
74 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -030075 .name = "YUV 4:2:2 packed, YCbYCr",
76 .fourcc = V4L2_PIX_FMT_YUYV,
77 .depth = 16,
78 .colplanes = 1,
79 .h_align = 2,
80 .v_align = 0,
81 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
82 SJPEG_FMT_FLAG_DEC_CAPTURE |
83 SJPEG_FMT_FLAG_EXYNOS3250 |
84 SJPEG_FMT_NON_RGB,
85 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
86 },
87 {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030088 .name = "YUV 4:2:2 packed, YCrYCb",
89 .fourcc = V4L2_PIX_FMT_YVYU,
90 .depth = 16,
91 .colplanes = 1,
92 .h_align = 1,
93 .v_align = 0,
94 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
95 SJPEG_FMT_FLAG_DEC_CAPTURE |
96 SJPEG_FMT_FLAG_EXYNOS4 |
97 SJPEG_FMT_NON_RGB,
98 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
99 },
100 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300101 .name = "YUV 4:2:2 packed, YCrYCb",
102 .fourcc = V4L2_PIX_FMT_YVYU,
103 .depth = 16,
104 .colplanes = 1,
105 .h_align = 2,
106 .v_align = 0,
107 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
108 SJPEG_FMT_FLAG_DEC_CAPTURE |
109 SJPEG_FMT_FLAG_EXYNOS3250 |
110 SJPEG_FMT_NON_RGB,
111 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
112 },
113 {
114 .name = "YUV 4:2:2 packed, YCrYCb",
115 .fourcc = V4L2_PIX_FMT_UYVY,
116 .depth = 16,
117 .colplanes = 1,
118 .h_align = 2,
119 .v_align = 0,
120 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
121 SJPEG_FMT_FLAG_DEC_CAPTURE |
122 SJPEG_FMT_FLAG_EXYNOS3250 |
123 SJPEG_FMT_NON_RGB,
124 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
125 },
126 {
127 .name = "YUV 4:2:2 packed, YCrYCb",
128 .fourcc = V4L2_PIX_FMT_VYUY,
129 .depth = 16,
130 .colplanes = 1,
131 .h_align = 2,
132 .v_align = 0,
133 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
134 SJPEG_FMT_FLAG_DEC_CAPTURE |
135 SJPEG_FMT_FLAG_EXYNOS3250 |
136 SJPEG_FMT_NON_RGB,
137 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
138 },
139 {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300140 .name = "RGB565",
141 .fourcc = V4L2_PIX_FMT_RGB565,
142 .depth = 16,
143 .colplanes = 1,
144 .h_align = 0,
145 .v_align = 0,
146 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
147 SJPEG_FMT_FLAG_DEC_CAPTURE |
148 SJPEG_FMT_FLAG_EXYNOS4 |
149 SJPEG_FMT_RGB,
150 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
151 },
152 {
153 .name = "RGB565",
154 .fourcc = V4L2_PIX_FMT_RGB565,
155 .depth = 16,
156 .colplanes = 1,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300157 .h_align = 2,
158 .v_align = 0,
159 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
160 SJPEG_FMT_FLAG_DEC_CAPTURE |
161 SJPEG_FMT_FLAG_EXYNOS3250 |
162 SJPEG_FMT_RGB,
163 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
164 },
165 {
166 .name = "RGB565X",
167 .fourcc = V4L2_PIX_FMT_RGB565X,
168 .depth = 16,
169 .colplanes = 1,
170 .h_align = 2,
171 .v_align = 0,
172 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
173 SJPEG_FMT_FLAG_DEC_CAPTURE |
174 SJPEG_FMT_FLAG_EXYNOS3250 |
175 SJPEG_FMT_RGB,
176 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
177 },
178 {
179 .name = "RGB565",
180 .fourcc = V4L2_PIX_FMT_RGB565,
181 .depth = 16,
182 .colplanes = 1,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300183 .h_align = 0,
184 .v_align = 0,
185 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
186 SJPEG_FMT_FLAG_S5P |
187 SJPEG_FMT_RGB,
188 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
189 },
190 {
191 .name = "ARGB8888, 32 bpp",
192 .fourcc = V4L2_PIX_FMT_RGB32,
193 .depth = 32,
194 .colplanes = 1,
195 .h_align = 0,
196 .v_align = 0,
197 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
198 SJPEG_FMT_FLAG_DEC_CAPTURE |
199 SJPEG_FMT_FLAG_EXYNOS4 |
200 SJPEG_FMT_RGB,
201 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
202 },
203 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300204 .name = "ARGB8888, 32 bpp",
205 .fourcc = V4L2_PIX_FMT_RGB32,
206 .depth = 32,
207 .colplanes = 1,
208 .h_align = 2,
209 .v_align = 0,
210 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
211 SJPEG_FMT_FLAG_DEC_CAPTURE |
212 SJPEG_FMT_FLAG_EXYNOS3250 |
213 SJPEG_FMT_RGB,
214 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
215 },
216 {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300217 .name = "YUV 4:4:4 planar, Y/CbCr",
218 .fourcc = V4L2_PIX_FMT_NV24,
219 .depth = 24,
220 .colplanes = 2,
221 .h_align = 0,
222 .v_align = 0,
223 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
224 SJPEG_FMT_FLAG_DEC_CAPTURE |
225 SJPEG_FMT_FLAG_EXYNOS4 |
226 SJPEG_FMT_NON_RGB,
227 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
228 },
229 {
230 .name = "YUV 4:4:4 planar, Y/CrCb",
231 .fourcc = V4L2_PIX_FMT_NV42,
232 .depth = 24,
233 .colplanes = 2,
234 .h_align = 0,
235 .v_align = 0,
236 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
237 SJPEG_FMT_FLAG_DEC_CAPTURE |
238 SJPEG_FMT_FLAG_EXYNOS4 |
239 SJPEG_FMT_NON_RGB,
240 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
241 },
242 {
243 .name = "YUV 4:2:2 planar, Y/CrCb",
244 .fourcc = V4L2_PIX_FMT_NV61,
245 .depth = 16,
246 .colplanes = 2,
247 .h_align = 1,
248 .v_align = 0,
249 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
250 SJPEG_FMT_FLAG_DEC_CAPTURE |
251 SJPEG_FMT_FLAG_EXYNOS4 |
252 SJPEG_FMT_NON_RGB,
253 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
254 },
255 {
256 .name = "YUV 4:2:2 planar, Y/CbCr",
257 .fourcc = V4L2_PIX_FMT_NV16,
258 .depth = 16,
259 .colplanes = 2,
260 .h_align = 1,
261 .v_align = 0,
262 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
263 SJPEG_FMT_FLAG_DEC_CAPTURE |
264 SJPEG_FMT_FLAG_EXYNOS4 |
265 SJPEG_FMT_NON_RGB,
266 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
267 },
268 {
269 .name = "YUV 4:2:0 planar, Y/CbCr",
270 .fourcc = V4L2_PIX_FMT_NV12,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300271 .depth = 12,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300272 .colplanes = 2,
273 .h_align = 1,
274 .v_align = 1,
275 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
276 SJPEG_FMT_FLAG_DEC_CAPTURE |
277 SJPEG_FMT_FLAG_EXYNOS4 |
278 SJPEG_FMT_NON_RGB,
279 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
280 },
281 {
282 .name = "YUV 4:2:0 planar, Y/CbCr",
283 .fourcc = V4L2_PIX_FMT_NV12,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300284 .depth = 12,
285 .colplanes = 2,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300286 .h_align = 3,
287 .v_align = 3,
288 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
289 SJPEG_FMT_FLAG_DEC_CAPTURE |
290 SJPEG_FMT_FLAG_EXYNOS3250 |
291 SJPEG_FMT_NON_RGB,
292 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
293 },
294 {
295 .name = "YUV 4:2:0 planar, Y/CbCr",
296 .fourcc = V4L2_PIX_FMT_NV12,
297 .depth = 12,
298 .colplanes = 2,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300299 .h_align = 4,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300300 .v_align = 4,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300301 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
302 SJPEG_FMT_FLAG_DEC_CAPTURE |
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300303 SJPEG_FMT_FLAG_S5P |
304 SJPEG_FMT_NON_RGB,
305 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
306 },
307 {
308 .name = "YUV 4:2:0 planar, Y/CrCb",
309 .fourcc = V4L2_PIX_FMT_NV21,
310 .depth = 12,
311 .colplanes = 2,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300312 .h_align = 3,
313 .v_align = 3,
314 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
315 SJPEG_FMT_FLAG_DEC_CAPTURE |
316 SJPEG_FMT_FLAG_EXYNOS3250 |
317 SJPEG_FMT_NON_RGB,
318 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
319 },
320 {
321 .name = "YUV 4:2:0 planar, Y/CrCb",
322 .fourcc = V4L2_PIX_FMT_NV21,
323 .depth = 12,
324 .colplanes = 2,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300325 .h_align = 1,
326 .v_align = 1,
327 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
328 SJPEG_FMT_FLAG_DEC_CAPTURE |
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300329 SJPEG_FMT_FLAG_EXYNOS3250 |
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300330 SJPEG_FMT_FLAG_EXYNOS4 |
331 SJPEG_FMT_NON_RGB,
332 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
333 },
334 {
335 .name = "YUV 4:2:0 contiguous 3-planar, Y/Cb/Cr",
336 .fourcc = V4L2_PIX_FMT_YUV420,
337 .depth = 12,
338 .colplanes = 3,
339 .h_align = 1,
340 .v_align = 1,
341 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
342 SJPEG_FMT_FLAG_DEC_CAPTURE |
343 SJPEG_FMT_FLAG_EXYNOS4 |
344 SJPEG_FMT_NON_RGB,
345 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
346 },
347 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300348 .name = "YUV 4:2:0 contiguous 3-planar, Y/Cb/Cr",
349 .fourcc = V4L2_PIX_FMT_YUV420,
350 .depth = 12,
351 .colplanes = 3,
352 .h_align = 4,
353 .v_align = 4,
354 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
355 SJPEG_FMT_FLAG_DEC_CAPTURE |
356 SJPEG_FMT_FLAG_EXYNOS3250 |
357 SJPEG_FMT_NON_RGB,
358 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
359 },
360 {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300361 .name = "Gray",
362 .fourcc = V4L2_PIX_FMT_GREY,
363 .depth = 8,
364 .colplanes = 1,
365 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
366 SJPEG_FMT_FLAG_DEC_CAPTURE |
367 SJPEG_FMT_FLAG_EXYNOS4 |
368 SJPEG_FMT_NON_RGB,
369 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300370 },
371};
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300372#define SJPEG_NUM_FORMATS ARRAY_SIZE(sjpeg_formats)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300373
374static const unsigned char qtbl_luminance[4][64] = {
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300375 {/*level 0 - high compression quality */
376 20, 16, 25, 39, 50, 46, 62, 68,
377 16, 18, 23, 38, 38, 53, 65, 68,
378 25, 23, 31, 38, 53, 65, 68, 68,
379 39, 38, 38, 53, 65, 68, 68, 68,
380 50, 38, 53, 65, 68, 68, 68, 68,
381 46, 53, 65, 68, 68, 68, 68, 68,
382 62, 65, 68, 68, 68, 68, 68, 68,
383 68, 68, 68, 68, 68, 68, 68, 68
384 },
385 {/* level 1 */
386 16, 11, 11, 16, 23, 27, 31, 30,
387 11, 12, 12, 15, 20, 23, 23, 30,
388 11, 12, 13, 16, 23, 26, 35, 47,
389 16, 15, 16, 23, 26, 37, 47, 64,
390 23, 20, 23, 26, 39, 51, 64, 64,
391 27, 23, 26, 37, 51, 64, 64, 64,
392 31, 23, 35, 47, 64, 64, 64, 64,
393 30, 30, 47, 64, 64, 64, 64, 64
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300394 },
395 {/* level 2 */
396 12, 8, 8, 12, 17, 21, 24, 23,
397 8, 9, 9, 11, 15, 19, 18, 23,
398 8, 9, 10, 12, 19, 20, 27, 36,
399 12, 11, 12, 21, 20, 28, 36, 53,
400 17, 15, 19, 20, 30, 39, 51, 59,
401 21, 19, 20, 28, 39, 51, 59, 59,
402 24, 18, 27, 36, 51, 59, 59, 59,
403 23, 23, 36, 53, 59, 59, 59, 59
404 },
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300405 {/* level 3 - low compression quality */
406 8, 6, 6, 8, 12, 14, 16, 17,
407 6, 6, 6, 8, 10, 13, 12, 15,
408 6, 6, 7, 8, 13, 14, 18, 24,
409 8, 8, 8, 14, 13, 19, 24, 35,
410 12, 10, 13, 13, 20, 26, 34, 39,
411 14, 13, 14, 19, 26, 34, 39, 39,
412 16, 12, 18, 24, 34, 39, 39, 39,
413 17, 15, 24, 35, 39, 39, 39, 39
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300414 }
415};
416
417static const unsigned char qtbl_chrominance[4][64] = {
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300418 {/*level 0 - high compression quality */
419 21, 25, 32, 38, 54, 68, 68, 68,
420 25, 28, 24, 38, 54, 68, 68, 68,
421 32, 24, 32, 43, 66, 68, 68, 68,
422 38, 38, 43, 53, 68, 68, 68, 68,
423 54, 54, 66, 68, 68, 68, 68, 68,
424 68, 68, 68, 68, 68, 68, 68, 68,
425 68, 68, 68, 68, 68, 68, 68, 68,
426 68, 68, 68, 68, 68, 68, 68, 68
427 },
428 {/* level 1 */
429 17, 15, 17, 21, 20, 26, 38, 48,
430 15, 19, 18, 17, 20, 26, 35, 43,
431 17, 18, 20, 22, 26, 30, 46, 53,
432 21, 17, 22, 28, 30, 39, 53, 64,
433 20, 20, 26, 30, 39, 48, 64, 64,
434 26, 26, 30, 39, 48, 63, 64, 64,
435 38, 35, 46, 53, 64, 64, 64, 64,
436 48, 43, 53, 64, 64, 64, 64, 64
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300437 },
438 {/* level 2 */
439 13, 11, 13, 16, 20, 20, 29, 37,
440 11, 14, 14, 14, 16, 20, 26, 32,
441 13, 14, 15, 17, 20, 23, 35, 40,
442 16, 14, 17, 21, 23, 30, 40, 50,
443 20, 16, 20, 23, 30, 37, 50, 59,
444 20, 20, 23, 30, 37, 48, 59, 59,
445 29, 26, 35, 40, 50, 59, 59, 59,
446 37, 32, 40, 50, 59, 59, 59, 59
447 },
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300448 {/* level 3 - low compression quality */
449 9, 8, 9, 11, 14, 17, 19, 24,
450 8, 10, 9, 11, 14, 13, 17, 22,
451 9, 9, 13, 14, 13, 15, 23, 26,
452 11, 11, 14, 14, 15, 20, 26, 33,
453 14, 14, 13, 15, 20, 24, 33, 39,
454 17, 13, 15, 20, 24, 32, 39, 39,
455 19, 17, 23, 26, 33, 39, 39, 39,
456 24, 22, 26, 33, 39, 39, 39, 39
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300457 }
458};
459
460static const unsigned char hdctbl0[16] = {
461 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
462};
463
464static const unsigned char hdctblg0[12] = {
465 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
466};
467static const unsigned char hactbl0[16] = {
468 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
469};
470static const unsigned char hactblg0[162] = {
471 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
472 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
473 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
474 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
475 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
476 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
477 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
478 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
479 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
480 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
481 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
482 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
483 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
484 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
485 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
486 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
487 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
488 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
489 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
490 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
491 0xf9, 0xfa
492};
493
Jacek Anaszewski337777a2013-11-22 06:13:34 -0300494/*
495 * Fourcc downgrade schema lookup tables for 422 and 420
496 * chroma subsampling - fourcc on each position maps on the
497 * fourcc from the table fourcc_to_dwngrd_schema_id which allows
498 * to get the most suitable fourcc counterpart for the given
499 * downgraded subsampling property.
500 */
501static const u32 subs422_fourcc_dwngrd_schema[] = {
502 V4L2_PIX_FMT_NV16,
503 V4L2_PIX_FMT_NV61,
504};
505
506static const u32 subs420_fourcc_dwngrd_schema[] = {
507 V4L2_PIX_FMT_NV12,
508 V4L2_PIX_FMT_NV21,
509 V4L2_PIX_FMT_NV12,
510 V4L2_PIX_FMT_NV21,
511 V4L2_PIX_FMT_NV12,
512 V4L2_PIX_FMT_NV21,
513 V4L2_PIX_FMT_GREY,
514 V4L2_PIX_FMT_GREY,
515 V4L2_PIX_FMT_GREY,
516 V4L2_PIX_FMT_GREY,
517};
518
519/*
520 * Lookup table for translation of a fourcc to the position
521 * of its downgraded counterpart in the *fourcc_dwngrd_schema
522 * tables.
523 */
524static const u32 fourcc_to_dwngrd_schema_id[] = {
525 V4L2_PIX_FMT_NV24,
526 V4L2_PIX_FMT_NV42,
527 V4L2_PIX_FMT_NV16,
528 V4L2_PIX_FMT_NV61,
529 V4L2_PIX_FMT_YUYV,
530 V4L2_PIX_FMT_YVYU,
531 V4L2_PIX_FMT_NV12,
532 V4L2_PIX_FMT_NV21,
533 V4L2_PIX_FMT_YUV420,
534 V4L2_PIX_FMT_GREY,
535};
536
537static int s5p_jpeg_get_dwngrd_sch_id_by_fourcc(u32 fourcc)
538{
539 int i;
540 for (i = 0; i < ARRAY_SIZE(fourcc_to_dwngrd_schema_id); ++i) {
541 if (fourcc_to_dwngrd_schema_id[i] == fourcc)
542 return i;
543 }
544
545 return -EINVAL;
546}
547
548static int s5p_jpeg_adjust_fourcc_to_subsampling(
549 enum v4l2_jpeg_chroma_subsampling subs,
550 u32 in_fourcc,
551 u32 *out_fourcc,
552 struct s5p_jpeg_ctx *ctx)
553{
554 int dwngrd_sch_id;
555
556 if (ctx->subsampling != V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
557 dwngrd_sch_id =
558 s5p_jpeg_get_dwngrd_sch_id_by_fourcc(in_fourcc);
559 if (dwngrd_sch_id < 0)
560 return -EINVAL;
561 }
562
563 switch (ctx->subsampling) {
564 case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
565 *out_fourcc = V4L2_PIX_FMT_GREY;
566 break;
567 case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
568 if (dwngrd_sch_id >
569 ARRAY_SIZE(subs420_fourcc_dwngrd_schema) - 1)
570 return -EINVAL;
571 *out_fourcc = subs420_fourcc_dwngrd_schema[dwngrd_sch_id];
572 break;
573 case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
574 if (dwngrd_sch_id >
575 ARRAY_SIZE(subs422_fourcc_dwngrd_schema) - 1)
576 return -EINVAL;
577 *out_fourcc = subs422_fourcc_dwngrd_schema[dwngrd_sch_id];
578 break;
579 default:
580 *out_fourcc = V4L2_PIX_FMT_GREY;
581 break;
582 }
583
584 return 0;
585}
586
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300587static int exynos4x12_decoded_subsampling[] = {
588 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
589 V4L2_JPEG_CHROMA_SUBSAMPLING_444,
590 V4L2_JPEG_CHROMA_SUBSAMPLING_422,
591 V4L2_JPEG_CHROMA_SUBSAMPLING_420,
592};
593
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300594static int exynos3250_decoded_subsampling[] = {
595 V4L2_JPEG_CHROMA_SUBSAMPLING_444,
596 V4L2_JPEG_CHROMA_SUBSAMPLING_422,
597 V4L2_JPEG_CHROMA_SUBSAMPLING_420,
598 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
599 -1,
600 -1,
601 V4L2_JPEG_CHROMA_SUBSAMPLING_411,
602};
603
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300604static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
605{
606 return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
607}
608
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300609static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh)
610{
611 return container_of(fh, struct s5p_jpeg_ctx, fh);
612}
613
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300614static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
615{
616 WARN_ON(ctx->subsampling > 3);
617
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300618 switch (ctx->jpeg->variant->version) {
619 case SJPEG_S5P:
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300620 if (ctx->subsampling > 2)
621 return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
622 return ctx->subsampling;
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300623 case SJPEG_EXYNOS3250:
624 if (ctx->subsampling > 3)
625 return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
626 return exynos3250_decoded_subsampling[ctx->subsampling];
627 case SJPEG_EXYNOS4:
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300628 if (ctx->subsampling > 2)
629 return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
630 return exynos4x12_decoded_subsampling[ctx->subsampling];
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300631 default:
632 return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300633 }
634}
635
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300636static inline void s5p_jpeg_set_qtbl(void __iomem *regs,
637 const unsigned char *qtbl,
638 unsigned long tab, int len)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300639{
640 int i;
641
642 for (i = 0; i < len; i++)
643 writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
644}
645
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300646static inline void s5p_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300647{
648 /* this driver fills quantisation table 0 with data for luma */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300649 s5p_jpeg_set_qtbl(regs, qtbl_luminance[quality],
650 S5P_JPG_QTBL_CONTENT(0),
651 ARRAY_SIZE(qtbl_luminance[quality]));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300652}
653
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300654static inline void s5p_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300655{
656 /* this driver fills quantisation table 1 with data for chroma */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300657 s5p_jpeg_set_qtbl(regs, qtbl_chrominance[quality],
658 S5P_JPG_QTBL_CONTENT(1),
659 ARRAY_SIZE(qtbl_chrominance[quality]));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300660}
661
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300662static inline void s5p_jpeg_set_htbl(void __iomem *regs,
663 const unsigned char *htbl,
664 unsigned long tab, int len)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300665{
666 int i;
667
668 for (i = 0; i < len; i++)
669 writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
670}
671
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300672static inline void s5p_jpeg_set_hdctbl(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300673{
674 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300675 s5p_jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0),
676 ARRAY_SIZE(hdctbl0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300677}
678
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300679static inline void s5p_jpeg_set_hdctblg(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300680{
681 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300682 s5p_jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0),
683 ARRAY_SIZE(hdctblg0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300684}
685
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300686static inline void s5p_jpeg_set_hactbl(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300687{
688 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300689 s5p_jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0),
690 ARRAY_SIZE(hactbl0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300691}
692
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300693static inline void s5p_jpeg_set_hactblg(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300694{
695 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300696 s5p_jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0),
697 ARRAY_SIZE(hactblg0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300698}
699
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300700static inline void exynos4_jpeg_set_tbl(void __iomem *regs,
701 const unsigned char *tbl,
702 unsigned long tab, int len)
703{
704 int i;
705 unsigned int dword;
706
707 for (i = 0; i < len; i += 4) {
708 dword = tbl[i] |
709 (tbl[i + 1] << 8) |
710 (tbl[i + 2] << 16) |
711 (tbl[i + 3] << 24);
712 writel(dword, regs + tab + i);
713 }
714}
715
716static inline void exynos4_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
717{
718 /* this driver fills quantisation table 0 with data for luma */
719 exynos4_jpeg_set_tbl(regs, qtbl_luminance[quality],
720 EXYNOS4_QTBL_CONTENT(0),
721 ARRAY_SIZE(qtbl_luminance[quality]));
722}
723
724static inline void exynos4_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
725{
726 /* this driver fills quantisation table 1 with data for chroma */
727 exynos4_jpeg_set_tbl(regs, qtbl_chrominance[quality],
728 EXYNOS4_QTBL_CONTENT(1),
729 ARRAY_SIZE(qtbl_chrominance[quality]));
730}
731
732void exynos4_jpeg_set_huff_tbl(void __iomem *base)
733{
734 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCLL,
735 ARRAY_SIZE(hdctbl0));
736 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCCL,
737 ARRAY_SIZE(hdctbl0));
738 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCLV,
739 ARRAY_SIZE(hdctblg0));
740 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCCV,
741 ARRAY_SIZE(hdctblg0));
742 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACLL,
743 ARRAY_SIZE(hactbl0));
744 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACCL,
745 ARRAY_SIZE(hactbl0));
746 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACLV,
747 ARRAY_SIZE(hactblg0));
748 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV,
749 ARRAY_SIZE(hactblg0));
750}
751
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300752/*
753 * ============================================================================
754 * Device file operations
755 * ============================================================================
756 */
757
758static int queue_init(void *priv, struct vb2_queue *src_vq,
759 struct vb2_queue *dst_vq);
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300760static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
761 __u32 pixelformat, unsigned int fmt_type);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300762static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300763
764static int s5p_jpeg_open(struct file *file)
765{
766 struct s5p_jpeg *jpeg = video_drvdata(file);
767 struct video_device *vfd = video_devdata(file);
768 struct s5p_jpeg_ctx *ctx;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300769 struct s5p_jpeg_fmt *out_fmt, *cap_fmt;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300770 int ret = 0;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300771
Sachin Kamatb5146c92012-08-16 08:52:58 -0300772 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300773 if (!ctx)
774 return -ENOMEM;
775
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300776 if (mutex_lock_interruptible(&jpeg->lock)) {
777 ret = -ERESTARTSYS;
778 goto free;
779 }
780
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300781 v4l2_fh_init(&ctx->fh, vfd);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300782 /* Use separate control handler per file handle */
783 ctx->fh.ctrl_handler = &ctx->ctrl_handler;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300784 file->private_data = &ctx->fh;
785 v4l2_fh_add(&ctx->fh);
786
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300787 ctx->jpeg = jpeg;
788 if (vfd == jpeg->vfd_encoder) {
789 ctx->mode = S5P_JPEG_ENCODE;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300790 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_RGB565,
791 FMT_TYPE_OUTPUT);
792 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
793 FMT_TYPE_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300794 } else {
795 ctx->mode = S5P_JPEG_DECODE;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300796 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
797 FMT_TYPE_OUTPUT);
798 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
799 FMT_TYPE_CAPTURE);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300800 ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300801 }
802
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300803 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
804 if (IS_ERR(ctx->fh.m2m_ctx)) {
805 ret = PTR_ERR(ctx->fh.m2m_ctx);
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300806 goto error;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300807 }
808
809 ctx->out_q.fmt = out_fmt;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300810 ctx->cap_q.fmt = cap_fmt;
811
812 ret = s5p_jpeg_controls_create(ctx);
813 if (ret < 0)
814 goto error;
815
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300816 mutex_unlock(&jpeg->lock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300817 return 0;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300818
819error:
820 v4l2_fh_del(&ctx->fh);
821 v4l2_fh_exit(&ctx->fh);
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300822 mutex_unlock(&jpeg->lock);
823free:
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300824 kfree(ctx);
825 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300826}
827
828static int s5p_jpeg_release(struct file *file)
829{
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300830 struct s5p_jpeg *jpeg = video_drvdata(file);
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300831 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300832
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300833 mutex_lock(&jpeg->lock);
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300834 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300835 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300836 v4l2_fh_del(&ctx->fh);
837 v4l2_fh_exit(&ctx->fh);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300838 kfree(ctx);
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300839 mutex_unlock(&jpeg->lock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300840
841 return 0;
842}
843
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300844static const struct v4l2_file_operations s5p_jpeg_fops = {
845 .owner = THIS_MODULE,
846 .open = s5p_jpeg_open,
847 .release = s5p_jpeg_release,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300848 .poll = v4l2_m2m_fop_poll,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300849 .unlocked_ioctl = video_ioctl2,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300850 .mmap = v4l2_m2m_fop_mmap,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300851};
852
853/*
854 * ============================================================================
855 * video ioctl operations
856 * ============================================================================
857 */
858
859static int get_byte(struct s5p_jpeg_buffer *buf)
860{
861 if (buf->curr >= buf->size)
862 return -1;
863
864 return ((unsigned char *)buf->data)[buf->curr++];
865}
866
867static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
868{
869 unsigned int temp;
870 int byte;
871
872 byte = get_byte(buf);
873 if (byte == -1)
874 return -1;
875 temp = byte << 8;
876 byte = get_byte(buf);
877 if (byte == -1)
878 return -1;
879 *word = (unsigned int)byte | temp;
880 return 0;
881}
882
883static void skip(struct s5p_jpeg_buffer *buf, long len)
884{
885 if (len <= 0)
886 return;
887
888 while (len--)
889 get_byte(buf);
890}
891
892static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
Jacek Anaszewskif8433962013-11-21 13:33:09 -0300893 unsigned long buffer, unsigned long size,
894 struct s5p_jpeg_ctx *ctx)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300895{
896 int c, components, notfound;
Jacek Anaszewskif8433962013-11-21 13:33:09 -0300897 unsigned int height, width, word, subsampling = 0;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300898 long length;
899 struct s5p_jpeg_buffer jpeg_buffer;
900
901 jpeg_buffer.size = size;
902 jpeg_buffer.data = buffer;
903 jpeg_buffer.curr = 0;
904
905 notfound = 1;
906 while (notfound) {
907 c = get_byte(&jpeg_buffer);
908 if (c == -1)
Jacek Anaszewskia35f6002014-07-11 12:19:43 -0300909 return false;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300910 if (c != 0xff)
911 continue;
912 do
913 c = get_byte(&jpeg_buffer);
914 while (c == 0xff);
915 if (c == -1)
Jacek Anaszewskia35f6002014-07-11 12:19:43 -0300916 return false;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300917 if (c == 0)
918 continue;
919 length = 0;
920 switch (c) {
921 /* SOF0: baseline JPEG */
922 case SOF0:
923 if (get_word_be(&jpeg_buffer, &word))
924 break;
925 if (get_byte(&jpeg_buffer) == -1)
926 break;
927 if (get_word_be(&jpeg_buffer, &height))
928 break;
929 if (get_word_be(&jpeg_buffer, &width))
930 break;
931 components = get_byte(&jpeg_buffer);
932 if (components == -1)
933 break;
934 notfound = 0;
935
Jacek Anaszewskif8433962013-11-21 13:33:09 -0300936 if (components == 1) {
937 subsampling = 0x33;
938 } else {
939 skip(&jpeg_buffer, 1);
940 subsampling = get_byte(&jpeg_buffer);
941 skip(&jpeg_buffer, 1);
942 }
943
944 skip(&jpeg_buffer, components * 2);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300945 break;
946
947 /* skip payload-less markers */
948 case RST ... RST + 7:
949 case SOI:
950 case EOI:
951 case TEM:
952 break;
953
954 /* skip uninteresting payload markers */
955 default:
956 if (get_word_be(&jpeg_buffer, &word))
957 break;
958 length = (long)word - 2;
959 skip(&jpeg_buffer, length);
960 break;
961 }
962 }
963 result->w = width;
964 result->h = height;
965 result->size = components;
Jacek Anaszewskif8433962013-11-21 13:33:09 -0300966
967 switch (subsampling) {
968 case 0x11:
969 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444;
970 break;
971 case 0x21:
972 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422;
973 break;
974 case 0x22:
975 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420;
976 break;
977 case 0x33:
978 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
979 break;
980 default:
981 return false;
982 }
983
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300984 return !notfound;
985}
986
987static int s5p_jpeg_querycap(struct file *file, void *priv,
988 struct v4l2_capability *cap)
989{
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300990 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300991
992 if (ctx->mode == S5P_JPEG_ENCODE) {
993 strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder",
994 sizeof(cap->driver));
995 strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
996 sizeof(cap->card));
997 } else {
998 strlcpy(cap->driver, S5P_JPEG_M2M_NAME " decoder",
999 sizeof(cap->driver));
1000 strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
1001 sizeof(cap->card));
1002 }
1003 cap->bus_info[0] = 0;
Sylwester Nawrockif0476a82012-07-26 09:30:00 -03001004 /*
1005 * This is only a mem-to-mem video device. The capture and output
1006 * device capability flags are left only for backward compatibility
1007 * and are scheduled for removal.
1008 */
1009 cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M |
1010 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001011 return 0;
1012}
1013
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001014static int enum_fmt(struct s5p_jpeg_fmt *sjpeg_formats, int n,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001015 struct v4l2_fmtdesc *f, u32 type)
1016{
1017 int i, num = 0;
1018
1019 for (i = 0; i < n; ++i) {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001020 if (sjpeg_formats[i].flags & type) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001021 /* index-th format of type type found ? */
1022 if (num == f->index)
1023 break;
1024 /* Correct type but haven't reached our index yet,
1025 * just increment per-type index */
1026 ++num;
1027 }
1028 }
1029
1030 /* Format not found */
1031 if (i >= n)
1032 return -EINVAL;
1033
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001034 strlcpy(f->description, sjpeg_formats[i].name, sizeof(f->description));
1035 f->pixelformat = sjpeg_formats[i].fourcc;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001036
1037 return 0;
1038}
1039
1040static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
1041 struct v4l2_fmtdesc *f)
1042{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001043 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001044
1045 if (ctx->mode == S5P_JPEG_ENCODE)
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001046 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
1047 SJPEG_FMT_FLAG_ENC_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001048
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001049 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
1050 SJPEG_FMT_FLAG_DEC_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001051}
1052
1053static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
1054 struct v4l2_fmtdesc *f)
1055{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001056 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001057
1058 if (ctx->mode == S5P_JPEG_ENCODE)
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001059 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
1060 SJPEG_FMT_FLAG_ENC_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001061
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001062 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
1063 SJPEG_FMT_FLAG_DEC_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001064}
1065
1066static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
1067 enum v4l2_buf_type type)
1068{
1069 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1070 return &ctx->out_q;
1071 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1072 return &ctx->cap_q;
1073
1074 return NULL;
1075}
1076
1077static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
1078{
1079 struct vb2_queue *vq;
1080 struct s5p_jpeg_q_data *q_data = NULL;
1081 struct v4l2_pix_format *pix = &f->fmt.pix;
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001082 struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001083
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001084 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001085 if (!vq)
1086 return -EINVAL;
1087
1088 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1089 ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
1090 return -EINVAL;
1091 q_data = get_q_data(ct, f->type);
1092 BUG_ON(q_data == NULL);
1093
1094 pix->width = q_data->w;
1095 pix->height = q_data->h;
1096 pix->field = V4L2_FIELD_NONE;
1097 pix->pixelformat = q_data->fmt->fourcc;
1098 pix->bytesperline = 0;
1099 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
1100 u32 bpl = q_data->w;
1101 if (q_data->fmt->colplanes == 1)
1102 bpl = (bpl * q_data->fmt->depth) >> 3;
1103 pix->bytesperline = bpl;
1104 }
1105 pix->sizeimage = q_data->size;
1106
1107 return 0;
1108}
1109
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001110static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
1111 u32 pixelformat, unsigned int fmt_type)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001112{
Jacek Anaszewskib2451682014-04-10 04:32:11 -03001113 unsigned int k, fmt_flag;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001114
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001115 if (ctx->mode == S5P_JPEG_ENCODE)
1116 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
1117 SJPEG_FMT_FLAG_ENC_OUTPUT :
1118 SJPEG_FMT_FLAG_ENC_CAPTURE;
1119 else
1120 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
1121 SJPEG_FMT_FLAG_DEC_OUTPUT :
1122 SJPEG_FMT_FLAG_DEC_CAPTURE;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001123
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001124 for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) {
1125 struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k];
1126 if (fmt->fourcc == pixelformat &&
1127 fmt->flags & fmt_flag &&
Jacek Anaszewskib2451682014-04-10 04:32:11 -03001128 fmt->flags & ctx->jpeg->variant->fmt_ver_flag) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001129 return fmt;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001130 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001131 }
1132
1133 return NULL;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001134}
1135
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001136static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
1137 u32 *w, unsigned int wmin, unsigned int wmax,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001138 unsigned int walign,
1139 u32 *h, unsigned int hmin, unsigned int hmax,
1140 unsigned int halign)
1141{
1142 int width, height, w_step, h_step;
1143
1144 width = *w;
1145 height = *h;
1146
1147 w_step = 1 << walign;
1148 h_step = 1 << halign;
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001149
1150 if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) {
1151 /*
1152 * Rightmost and bottommost pixels are cropped by the
1153 * Exynos3250 JPEG IP for RGB formats, for the specific
1154 * width and height values respectively. This assignment
1155 * will result in v4l_bound_align_image returning dimensions
1156 * reduced by 1 for the aforementioned cases.
1157 */
1158 if (w_step == 4 && ((width & 3) == 1)) {
1159 wmax = width;
1160 hmax = height;
1161 }
1162 }
1163
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001164 v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
1165
1166 if (*w < width && (*w + w_step) < wmax)
1167 *w += w_step;
1168 if (*h < height && (*h + h_step) < hmax)
1169 *h += h_step;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001170}
1171
1172static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
1173 struct s5p_jpeg_ctx *ctx, int q_type)
1174{
1175 struct v4l2_pix_format *pix = &f->fmt.pix;
1176
1177 if (pix->field == V4L2_FIELD_ANY)
1178 pix->field = V4L2_FIELD_NONE;
1179 else if (pix->field != V4L2_FIELD_NONE)
1180 return -EINVAL;
1181
1182 /* V4L2 specification suggests the driver corrects the format struct
1183 * if any of the dimensions is unsupported */
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001184 if (q_type == FMT_TYPE_OUTPUT)
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001185 jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001186 S5P_JPEG_MAX_WIDTH, 0,
1187 &pix->height, S5P_JPEG_MIN_HEIGHT,
1188 S5P_JPEG_MAX_HEIGHT, 0);
1189 else
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001190 jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001191 S5P_JPEG_MAX_WIDTH, fmt->h_align,
1192 &pix->height, S5P_JPEG_MIN_HEIGHT,
1193 S5P_JPEG_MAX_HEIGHT, fmt->v_align);
1194
1195 if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
1196 if (pix->sizeimage <= 0)
1197 pix->sizeimage = PAGE_SIZE;
1198 pix->bytesperline = 0;
1199 } else {
1200 u32 bpl = pix->bytesperline;
1201
1202 if (fmt->colplanes > 1 && bpl < pix->width)
1203 bpl = pix->width; /* planar */
1204
1205 if (fmt->colplanes == 1 && /* packed */
Jacek Anaszewskicc690902013-11-25 06:58:10 -03001206 (bpl << 3) / fmt->depth < pix->width)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001207 bpl = (pix->width * fmt->depth) >> 3;
1208
1209 pix->bytesperline = bpl;
1210 pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
1211 }
1212
1213 return 0;
1214}
1215
1216static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
1217 struct v4l2_format *f)
1218{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001219 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001220 struct v4l2_pix_format *pix = &f->fmt.pix;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001221 struct s5p_jpeg_fmt *fmt;
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001222 int ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001223
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001224 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1225 FMT_TYPE_CAPTURE);
1226 if (!fmt) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001227 v4l2_err(&ctx->jpeg->v4l2_dev,
1228 "Fourcc format (0x%08x) invalid.\n",
1229 f->fmt.pix.pixelformat);
1230 return -EINVAL;
1231 }
1232
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001233 if ((ctx->jpeg->variant->version != SJPEG_EXYNOS4) ||
1234 (ctx->mode != S5P_JPEG_DECODE))
1235 goto exit;
1236
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001237 /*
1238 * The exynos4x12 device requires resulting YUV image
1239 * subsampling not to be lower than the input jpeg subsampling.
1240 * If this requirement is not met then downgrade the requested
1241 * capture format to the one with subsampling equal to the input jpeg.
1242 */
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001243 if ((fmt->flags & SJPEG_FMT_NON_RGB) &&
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001244 (fmt->subsampling < ctx->subsampling)) {
1245 ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
1246 fmt->fourcc,
1247 &pix->pixelformat,
1248 ctx);
1249 if (ret < 0)
1250 pix->pixelformat = V4L2_PIX_FMT_GREY;
1251
1252 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1253 FMT_TYPE_CAPTURE);
1254 }
1255
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001256 /*
1257 * Decompression of a JPEG file with 4:2:0 subsampling and odd
1258 * width to the YUV 4:2:0 compliant formats produces a raw image
1259 * with broken luma component. Adjust capture format to RGB565
1260 * in such a case.
1261 */
1262 if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
1263 (ctx->out_q.w & 1) &&
1264 (pix->pixelformat == V4L2_PIX_FMT_NV12 ||
1265 pix->pixelformat == V4L2_PIX_FMT_NV21 ||
1266 pix->pixelformat == V4L2_PIX_FMT_YUV420)) {
1267 pix->pixelformat = V4L2_PIX_FMT_RGB565;
1268 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1269 FMT_TYPE_CAPTURE);
1270 }
1271
1272exit:
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001273 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001274}
1275
1276static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
1277 struct v4l2_format *f)
1278{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001279 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001280 struct s5p_jpeg_fmt *fmt;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001281
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001282 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1283 FMT_TYPE_OUTPUT);
1284 if (!fmt) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001285 v4l2_err(&ctx->jpeg->v4l2_dev,
1286 "Fourcc format (0x%08x) invalid.\n",
1287 f->fmt.pix.pixelformat);
1288 return -EINVAL;
1289 }
1290
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001291 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001292}
1293
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001294static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
1295 struct v4l2_format *f,
1296 int fmt_depth)
1297{
1298 struct v4l2_pix_format *pix = &f->fmt.pix;
1299 u32 pix_fmt = f->fmt.pix.pixelformat;
1300 int w = pix->width, h = pix->height, wh_align;
1301
1302 if (pix_fmt == V4L2_PIX_FMT_RGB32 ||
1303 pix_fmt == V4L2_PIX_FMT_NV24 ||
1304 pix_fmt == V4L2_PIX_FMT_NV42 ||
1305 pix_fmt == V4L2_PIX_FMT_NV12 ||
1306 pix_fmt == V4L2_PIX_FMT_NV21 ||
1307 pix_fmt == V4L2_PIX_FMT_YUV420)
1308 wh_align = 4;
1309 else
1310 wh_align = 1;
1311
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001312 jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH,
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001313 S5P_JPEG_MAX_WIDTH, wh_align,
1314 &h, S5P_JPEG_MIN_HEIGHT,
1315 S5P_JPEG_MAX_HEIGHT, wh_align);
1316
1317 return w * h * fmt_depth >> 3;
1318}
1319
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001320static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
1321{
1322 struct vb2_queue *vq;
1323 struct s5p_jpeg_q_data *q_data = NULL;
1324 struct v4l2_pix_format *pix = &f->fmt.pix;
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001325 struct v4l2_ctrl *ctrl_subs;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001326 unsigned int f_type;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001327
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001328 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001329 if (!vq)
1330 return -EINVAL;
1331
1332 q_data = get_q_data(ct, f->type);
1333 BUG_ON(q_data == NULL);
1334
1335 if (vb2_is_busy(vq)) {
1336 v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
1337 return -EBUSY;
1338 }
1339
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001340 f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
1341 FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;
1342
1343 q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001344 q_data->w = pix->width;
1345 q_data->h = pix->height;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001346 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
1347 /*
1348 * During encoding Exynos4x12 SoCs access wider memory area
1349 * than it results from Image_x and Image_y values written to
1350 * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu
1351 * page fault calculate proper buffer size in such a case.
1352 */
1353 if (ct->jpeg->variant->version == SJPEG_EXYNOS4 &&
1354 f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)
1355 q_data->size = exynos4_jpeg_get_output_buffer_size(ct,
1356 f,
1357 q_data->fmt->depth);
1358 else
1359 q_data->size = q_data->w * q_data->h *
1360 q_data->fmt->depth >> 3;
1361 } else {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001362 q_data->size = pix->sizeimage;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001363 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001364
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001365 if (f_type == FMT_TYPE_OUTPUT) {
1366 ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler,
1367 V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
1368 if (ctrl_subs)
1369 v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
Jacek Anaszewskidfd96902014-07-11 12:19:46 -03001370 ct->crop_altered = false;
1371 }
1372
1373 /*
1374 * For decoding init crop_rect with capture buffer dimmensions which
1375 * contain aligned dimensions of the input JPEG image and do it only
1376 * if crop rectangle hasn't been altered by the user space e.g. with
1377 * S_SELECTION ioctl. For encoding assign output buffer dimensions.
1378 */
1379 if (!ct->crop_altered &&
1380 ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) ||
1381 (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) {
1382 ct->crop_rect.width = pix->width;
1383 ct->crop_rect.height = pix->height;
1384 }
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001385 }
1386
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001387 return 0;
1388}
1389
1390static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
1391 struct v4l2_format *f)
1392{
1393 int ret;
1394
1395 ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
1396 if (ret)
1397 return ret;
1398
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001399 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001400}
1401
1402static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
1403 struct v4l2_format *f)
1404{
1405 int ret;
1406
1407 ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
1408 if (ret)
1409 return ret;
1410
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001411 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001412}
1413
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001414static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
1415 struct v4l2_rect *r)
1416{
1417 int w_ratio, h_ratio, scale_factor, cur_ratio, i;
1418
1419 w_ratio = ctx->out_q.w / r->width;
1420 h_ratio = ctx->out_q.h / r->height;
1421
1422 scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio;
1423 scale_factor = clamp_val(scale_factor, 1, 8);
1424
1425 /* Align scale ratio to the nearest power of 2 */
1426 for (i = 0; i <= 3; ++i) {
1427 cur_ratio = 1 << i;
1428 if (scale_factor <= cur_ratio) {
1429 ctx->scale_factor = cur_ratio;
1430 break;
1431 }
1432 }
1433
1434 r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);
1435 r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);
1436
1437 ctx->crop_rect.width = r->width;
1438 ctx->crop_rect.height = r->height;
1439 ctx->crop_rect.left = 0;
1440 ctx->crop_rect.top = 0;
1441
1442 ctx->crop_altered = true;
1443
1444 return 0;
1445}
1446
1447/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
1448static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
1449{
1450 if (a->left < b->left || a->top < b->top)
1451 return 0;
1452 if (a->left + a->width > b->left + b->width)
1453 return 0;
1454 if (a->top + a->height > b->top + b->height)
1455 return 0;
1456
1457 return 1;
1458}
1459
1460static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,
1461 struct v4l2_rect *r)
1462{
1463 struct v4l2_rect base_rect;
1464 int w_step, h_step;
1465
1466 switch (ctx->cap_q.fmt->fourcc) {
1467 case V4L2_PIX_FMT_NV12:
1468 case V4L2_PIX_FMT_NV21:
1469 w_step = 1;
1470 h_step = 2;
1471 break;
1472 case V4L2_PIX_FMT_YUV420:
1473 w_step = 2;
1474 h_step = 2;
1475 break;
1476 default:
1477 w_step = 1;
1478 h_step = 1;
1479 break;
1480 }
1481
1482 base_rect.top = 0;
1483 base_rect.left = 0;
1484 base_rect.width = ctx->out_q.w;
1485 base_rect.height = ctx->out_q.h;
1486
1487 r->width = round_down(r->width, w_step);
1488 r->height = round_down(r->height, h_step);
1489 r->left = round_down(r->left, 2);
1490 r->top = round_down(r->top, 2);
1491
1492 if (!enclosed_rectangle(r, &base_rect))
1493 return -EINVAL;
1494
1495 ctx->crop_rect.left = r->left;
1496 ctx->crop_rect.top = r->top;
1497 ctx->crop_rect.width = r->width;
1498 ctx->crop_rect.height = r->height;
1499
1500 ctx->crop_altered = true;
1501
1502 return 0;
1503}
1504
1505/*
1506 * V4L2 controls
1507 */
1508
Sachin Kamat9f3bd322012-05-10 03:38:40 -03001509static int s5p_jpeg_g_selection(struct file *file, void *priv,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001510 struct v4l2_selection *s)
1511{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001512 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001513
1514 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
Jacek Anaszewski38a6ef32014-04-10 04:32:15 -03001515 s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001516 return -EINVAL;
1517
1518 /* For JPEG blob active == default == bounds */
1519 switch (s->target) {
Sylwester Nawrockic1334822012-05-20 11:17:12 -03001520 case V4L2_SEL_TGT_CROP:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001521 case V4L2_SEL_TGT_CROP_BOUNDS:
1522 case V4L2_SEL_TGT_CROP_DEFAULT:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001523 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1524 s->r.width = ctx->out_q.w;
1525 s->r.height = ctx->out_q.h;
Jacek Anaszewskifac4d962014-07-11 12:19:45 -03001526 s->r.left = 0;
1527 s->r.top = 0;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001528 break;
Jacek Anaszewskifac4d962014-07-11 12:19:45 -03001529 case V4L2_SEL_TGT_COMPOSE:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001530 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1531 case V4L2_SEL_TGT_COMPOSE_PADDED:
Jacek Anaszewskifac4d962014-07-11 12:19:45 -03001532 s->r.width = ctx->crop_rect.width;
1533 s->r.height = ctx->crop_rect.height;
1534 s->r.left = ctx->crop_rect.left;
1535 s->r.top = ctx->crop_rect.top;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001536 break;
1537 default:
1538 return -EINVAL;
1539 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001540 return 0;
1541}
1542
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001543/*
1544 * V4L2 controls
1545 */
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001546static int s5p_jpeg_s_selection(struct file *file, void *fh,
1547 struct v4l2_selection *s)
1548{
1549 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
1550 struct v4l2_rect *rect = &s->r;
1551 int ret = -EINVAL;
1552
1553 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1554 return -EINVAL;
1555
1556 if (s->target == V4L2_SEL_TGT_COMPOSE) {
1557 if (ctx->mode != S5P_JPEG_DECODE)
1558 return -EINVAL;
1559 if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
1560 ret = exynos3250_jpeg_try_downscale(ctx, rect);
1561 } else if (s->target == V4L2_SEL_TGT_CROP) {
1562 if (ctx->mode != S5P_JPEG_ENCODE)
1563 return -EINVAL;
1564 if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
1565 ret = exynos3250_jpeg_try_crop(ctx, rect);
1566 }
1567
1568 return ret;
1569}
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001570
1571static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001572{
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001573 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1574 struct s5p_jpeg *jpeg = ctx->jpeg;
1575 unsigned long flags;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001576
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001577 switch (ctrl->id) {
1578 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1579 spin_lock_irqsave(&jpeg->slock, flags);
Jacek Anaszewski303b0a92013-12-18 11:14:00 -03001580 ctrl->val = s5p_jpeg_to_user_subsampling(ctx);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001581 spin_unlock_irqrestore(&jpeg->slock, flags);
1582 break;
1583 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001584
1585 return 0;
1586}
1587
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001588static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
1589{
1590 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1591 unsigned long flags;
1592 int ret = 0;
1593
1594 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1595
1596 if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING) {
1597 if (ctx->jpeg->variant->version == SJPEG_S5P)
1598 goto error_free;
1599 /*
1600 * The exynos4x12 device requires input raw image fourcc
1601 * to be V4L2_PIX_FMT_GREY if gray jpeg format
1602 * is to be set.
1603 */
1604 if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
1605 ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
1606 ret = -EINVAL;
1607 goto error_free;
1608 }
1609 /*
1610 * The exynos4x12 device requires resulting jpeg subsampling
1611 * not to be lower than the input raw image subsampling.
1612 */
1613 if (ctx->out_q.fmt->subsampling > ctrl->val)
1614 ctrl->val = ctx->out_q.fmt->subsampling;
1615 }
1616
1617error_free:
1618 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1619 return ret;
1620}
1621
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001622static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001623{
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001624 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1625 unsigned long flags;
1626
1627 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1628
1629 switch (ctrl->id) {
1630 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -03001631 ctx->compr_quality = ctrl->val;
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001632 break;
1633 case V4L2_CID_JPEG_RESTART_INTERVAL:
1634 ctx->restart_interval = ctrl->val;
1635 break;
1636 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1637 ctx->subsampling = ctrl->val;
1638 break;
1639 }
1640
1641 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1642 return 0;
1643}
1644
1645static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {
1646 .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl,
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001647 .try_ctrl = s5p_jpeg_try_ctrl,
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001648 .s_ctrl = s5p_jpeg_s_ctrl,
1649};
1650
1651static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)
1652{
1653 unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */
1654 struct v4l2_ctrl *ctrl;
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001655 int ret;
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001656
1657 v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
1658
1659 if (ctx->mode == S5P_JPEG_ENCODE) {
1660 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1661 V4L2_CID_JPEG_COMPRESSION_QUALITY,
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -03001662 0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001663
1664 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1665 V4L2_CID_JPEG_RESTART_INTERVAL,
1666 0, 3, 0xffff, 0);
Jacek Anaszewskifdf9e2b2013-11-21 13:33:41 -03001667 if (ctx->jpeg->variant->version == SJPEG_S5P)
1668 mask = ~0x06; /* 422, 420 */
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001669 }
1670
1671 ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1672 V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
1673 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,
1674 V4L2_JPEG_CHROMA_SUBSAMPLING_422);
1675
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001676 if (ctx->ctrl_handler.error) {
1677 ret = ctx->ctrl_handler.error;
1678 goto error_free;
1679 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001680
1681 if (ctx->mode == S5P_JPEG_DECODE)
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001682 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |
1683 V4L2_CTRL_FLAG_READ_ONLY;
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001684
1685 ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
1686 if (ret < 0)
1687 goto error_free;
1688
1689 return ret;
1690
1691error_free:
1692 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1693 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001694}
1695
1696static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
1697 .vidioc_querycap = s5p_jpeg_querycap,
1698
1699 .vidioc_enum_fmt_vid_cap = s5p_jpeg_enum_fmt_vid_cap,
1700 .vidioc_enum_fmt_vid_out = s5p_jpeg_enum_fmt_vid_out,
1701
1702 .vidioc_g_fmt_vid_cap = s5p_jpeg_g_fmt,
1703 .vidioc_g_fmt_vid_out = s5p_jpeg_g_fmt,
1704
1705 .vidioc_try_fmt_vid_cap = s5p_jpeg_try_fmt_vid_cap,
1706 .vidioc_try_fmt_vid_out = s5p_jpeg_try_fmt_vid_out,
1707
1708 .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap,
1709 .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out,
1710
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001711 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1712 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1713 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1714 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001715
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001716 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
1717 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001718
1719 .vidioc_g_selection = s5p_jpeg_g_selection,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001720 .vidioc_s_selection = s5p_jpeg_s_selection,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001721};
1722
1723/*
1724 * ============================================================================
1725 * mem2mem callbacks
1726 * ============================================================================
1727 */
1728
1729static void s5p_jpeg_device_run(void *priv)
1730{
1731 struct s5p_jpeg_ctx *ctx = priv;
1732 struct s5p_jpeg *jpeg = ctx->jpeg;
1733 struct vb2_buffer *src_buf, *dst_buf;
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03001734 unsigned long src_addr, dst_addr, flags;
1735
1736 spin_lock_irqsave(&ctx->jpeg->slock, flags);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001737
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001738 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1739 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001740 src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
1741 dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
1742
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001743 s5p_jpeg_reset(jpeg->regs);
1744 s5p_jpeg_poweron(jpeg->regs);
1745 s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001746 if (ctx->mode == S5P_JPEG_ENCODE) {
1747 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001748 s5p_jpeg_input_raw_mode(jpeg->regs,
1749 S5P_JPEG_RAW_IN_565);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001750 else
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001751 s5p_jpeg_input_raw_mode(jpeg->regs,
1752 S5P_JPEG_RAW_IN_422);
1753 s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
1754 s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);
1755 s5p_jpeg_x(jpeg->regs, ctx->out_q.w);
1756 s5p_jpeg_y(jpeg->regs, ctx->out_q.h);
1757 s5p_jpeg_imgadr(jpeg->regs, src_addr);
1758 s5p_jpeg_jpgadr(jpeg->regs, dst_addr);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001759
1760 /* ultimately comes from sizeimage from userspace */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001761 s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001762
1763 /* JPEG RGB to YCbCr conversion matrix */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001764 s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
1765 s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
1766 s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
1767 s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
1768 s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
1769 s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
1770 s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
1771 s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
1772 s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001773
1774 /*
1775 * JPEG IP allows storing 4 quantization tables
1776 * We fill table 0 for luma and table 1 for chroma
1777 */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03001778 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1779 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001780 /* use table 0 for Y */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001781 s5p_jpeg_qtbl(jpeg->regs, 1, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001782 /* use table 1 for Cb and Cr*/
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001783 s5p_jpeg_qtbl(jpeg->regs, 2, 1);
1784 s5p_jpeg_qtbl(jpeg->regs, 3, 1);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001785
1786 /* Y, Cb, Cr use Huffman table 0 */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001787 s5p_jpeg_htbl_ac(jpeg->regs, 1);
1788 s5p_jpeg_htbl_dc(jpeg->regs, 1);
1789 s5p_jpeg_htbl_ac(jpeg->regs, 2);
1790 s5p_jpeg_htbl_dc(jpeg->regs, 2);
1791 s5p_jpeg_htbl_ac(jpeg->regs, 3);
1792 s5p_jpeg_htbl_dc(jpeg->regs, 3);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001793 } else { /* S5P_JPEG_DECODE */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001794 s5p_jpeg_rst_int_enable(jpeg->regs, true);
1795 s5p_jpeg_data_num_int_enable(jpeg->regs, true);
1796 s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001797 if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001798 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001799 else
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001800 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
1801 s5p_jpeg_jpgadr(jpeg->regs, src_addr);
1802 s5p_jpeg_imgadr(jpeg->regs, dst_addr);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001803 }
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001804
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001805 s5p_jpeg_start(jpeg->regs);
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03001806
1807 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001808}
1809
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001810static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
1811{
1812 struct s5p_jpeg *jpeg = ctx->jpeg;
1813 struct s5p_jpeg_fmt *fmt;
1814 struct vb2_buffer *vb;
1815 struct s5p_jpeg_addr jpeg_addr;
1816 u32 pix_size, padding_bytes = 0;
1817
1818 pix_size = ctx->cap_q.w * ctx->cap_q.h;
1819
1820 if (ctx->mode == S5P_JPEG_ENCODE) {
1821 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1822 fmt = ctx->out_q.fmt;
1823 if (ctx->out_q.w % 2 && fmt->h_align > 0)
1824 padding_bytes = ctx->out_q.h;
1825 } else {
1826 fmt = ctx->cap_q.fmt;
1827 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1828 }
1829
1830 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
1831
1832 if (fmt->colplanes == 2) {
1833 jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;
1834 } else if (fmt->colplanes == 3) {
1835 jpeg_addr.cb = jpeg_addr.y + pix_size;
1836 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
1837 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
1838 else
1839 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
1840 }
1841
1842 exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);
1843}
1844
1845static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
1846{
1847 struct s5p_jpeg *jpeg = ctx->jpeg;
1848 struct vb2_buffer *vb;
1849 unsigned int jpeg_addr = 0;
1850
1851 if (ctx->mode == S5P_JPEG_ENCODE)
1852 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1853 else
1854 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1855
1856 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1857 exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
1858}
1859
1860static void exynos4_jpeg_device_run(void *priv)
1861{
1862 struct s5p_jpeg_ctx *ctx = priv;
1863 struct s5p_jpeg *jpeg = ctx->jpeg;
1864 unsigned int bitstream_size;
1865 unsigned long flags;
1866
1867 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1868
1869 if (ctx->mode == S5P_JPEG_ENCODE) {
1870 exynos4_jpeg_sw_reset(jpeg->regs);
1871 exynos4_jpeg_set_interrupt(jpeg->regs);
1872 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
1873
1874 exynos4_jpeg_set_huff_tbl(jpeg->regs);
1875
1876 /*
1877 * JPEG IP allows storing 4 quantization tables
1878 * We fill table 0 for luma and table 1 for chroma
1879 */
1880 exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1881 exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
1882
1883 exynos4_jpeg_set_encode_tbl_select(jpeg->regs,
1884 ctx->compr_quality);
1885 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
1886 ctx->cap_q.h);
1887
1888 exynos4_jpeg_set_enc_out_fmt(jpeg->regs, ctx->subsampling);
1889 exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->out_q.fmt->fourcc);
1890 exynos4_jpeg_set_img_addr(ctx);
1891 exynos4_jpeg_set_jpeg_addr(ctx);
1892 exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
1893 ctx->out_q.fmt->fourcc);
1894 } else {
1895 exynos4_jpeg_sw_reset(jpeg->regs);
1896 exynos4_jpeg_set_interrupt(jpeg->regs);
1897 exynos4_jpeg_set_img_addr(ctx);
1898 exynos4_jpeg_set_jpeg_addr(ctx);
1899 exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->cap_q.fmt->fourcc);
1900
1901 bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
1902
1903 exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
1904 }
1905
1906 exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
1907
1908 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1909}
1910
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001911static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
1912{
1913 struct s5p_jpeg *jpeg = ctx->jpeg;
1914 struct s5p_jpeg_fmt *fmt;
1915 struct vb2_buffer *vb;
1916 struct s5p_jpeg_addr jpeg_addr;
1917 u32 pix_size;
1918
1919 pix_size = ctx->cap_q.w * ctx->cap_q.h;
1920
1921 if (ctx->mode == S5P_JPEG_ENCODE) {
1922 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1923 fmt = ctx->out_q.fmt;
1924 } else {
1925 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1926 fmt = ctx->cap_q.fmt;
1927 }
1928
1929 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
1930
1931 if (fmt->colplanes == 2) {
1932 jpeg_addr.cb = jpeg_addr.y + pix_size;
1933 } else if (fmt->colplanes == 3) {
1934 jpeg_addr.cb = jpeg_addr.y + pix_size;
1935 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
1936 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
1937 else
1938 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
1939 }
1940
1941 exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);
1942}
1943
1944static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
1945{
1946 struct s5p_jpeg *jpeg = ctx->jpeg;
1947 struct vb2_buffer *vb;
1948 unsigned int jpeg_addr = 0;
1949
1950 if (ctx->mode == S5P_JPEG_ENCODE)
1951 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1952 else
1953 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1954
1955 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1956 exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);
1957}
1958
1959static void exynos3250_jpeg_device_run(void *priv)
1960{
1961 struct s5p_jpeg_ctx *ctx = priv;
1962 struct s5p_jpeg *jpeg = ctx->jpeg;
1963 unsigned long flags;
1964
1965 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1966
1967 exynos3250_jpeg_reset(jpeg->regs);
1968 exynos3250_jpeg_set_dma_num(jpeg->regs);
1969 exynos3250_jpeg_poweron(jpeg->regs);
1970 exynos3250_jpeg_clk_set(jpeg->regs);
1971 exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);
1972
1973 if (ctx->mode == S5P_JPEG_ENCODE) {
1974 exynos3250_jpeg_input_raw_fmt(jpeg->regs,
1975 ctx->out_q.fmt->fourcc);
1976 exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);
1977
1978 /*
1979 * JPEG IP allows storing 4 quantization tables
1980 * We fill table 0 for luma and table 1 for chroma
1981 */
1982 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1983 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
1984 /* use table 0 for Y */
1985 exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);
1986 /* use table 1 for Cb and Cr*/
1987 exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
1988 exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
1989
1990 /* Y, Cb, Cr use Huffman table 0 */
1991 exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
1992 exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
1993 exynos3250_jpeg_htbl_ac(jpeg->regs, 2);
1994 exynos3250_jpeg_htbl_dc(jpeg->regs, 2);
1995 exynos3250_jpeg_htbl_ac(jpeg->regs, 3);
1996 exynos3250_jpeg_htbl_dc(jpeg->regs, 3);
1997
1998 exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);
1999 exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);
2000 exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,
2001 ctx->out_q.w);
2002 exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,
2003 ctx->crop_rect.top);
2004 exynos3250_jpeg_set_img_addr(ctx);
2005 exynos3250_jpeg_set_jpeg_addr(ctx);
2006 exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
2007
2008 /* ultimately comes from sizeimage from userspace */
2009 exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);
2010
2011 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||
2012 ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||
2013 ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
2014 exynos3250_jpeg_set_y16(jpeg->regs, true);
2015 } else {
2016 exynos3250_jpeg_set_img_addr(ctx);
2017 exynos3250_jpeg_set_jpeg_addr(ctx);
2018 exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,
2019 ctx->cap_q.w);
2020 exynos3250_jpeg_offset(jpeg->regs, 0, 0);
2021 exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,
2022 ctx->scale_factor);
2023 exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);
2024 exynos3250_jpeg_output_raw_fmt(jpeg->regs,
2025 ctx->cap_q.fmt->fourcc);
2026 }
2027
2028 exynos3250_jpeg_interrupts_enable(jpeg->regs);
2029
2030 /* JPEG RGB to YCbCr conversion matrix */
2031 exynos3250_jpeg_coef(jpeg->regs, ctx->mode);
2032
2033 exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);
2034 jpeg->irq_status = 0;
2035 exynos3250_jpeg_start(jpeg->regs);
2036
2037 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
2038}
2039
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002040static int s5p_jpeg_job_ready(void *priv)
2041{
2042 struct s5p_jpeg_ctx *ctx = priv;
2043
2044 if (ctx->mode == S5P_JPEG_DECODE)
2045 return ctx->hdr_parsed;
2046 return 1;
2047}
2048
2049static void s5p_jpeg_job_abort(void *priv)
2050{
2051}
2052
2053static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
2054 .device_run = s5p_jpeg_device_run,
2055 .job_ready = s5p_jpeg_job_ready,
2056 .job_abort = s5p_jpeg_job_abort,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002057};
2058
2059static struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {
2060 .device_run = exynos3250_jpeg_device_run,
2061 .job_ready = s5p_jpeg_job_ready,
2062 .job_abort = s5p_jpeg_job_abort,
2063};
2064
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002065static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002066 .device_run = exynos4_jpeg_device_run,
2067 .job_ready = s5p_jpeg_job_ready,
2068 .job_abort = s5p_jpeg_job_abort,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002069};
2070
2071/*
2072 * ============================================================================
2073 * Queue operations
2074 * ============================================================================
2075 */
2076
Marek Szyprowski719c1742012-01-13 05:12:38 -03002077static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
2078 const struct v4l2_format *fmt,
2079 unsigned int *nbuffers, unsigned int *nplanes,
2080 unsigned int sizes[], void *alloc_ctxs[])
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002081{
2082 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
2083 struct s5p_jpeg_q_data *q_data = NULL;
2084 unsigned int size, count = *nbuffers;
2085
2086 q_data = get_q_data(ctx, vq->type);
2087 BUG_ON(q_data == NULL);
2088
2089 size = q_data->size;
2090
2091 /*
2092 * header is parsed during decoding and parsed information stored
2093 * in the context so we do not allow another buffer to overwrite it
2094 */
2095 if (ctx->mode == S5P_JPEG_DECODE)
2096 count = 1;
2097
2098 *nbuffers = count;
2099 *nplanes = 1;
2100 sizes[0] = size;
2101 alloc_ctxs[0] = ctx->jpeg->alloc_ctx;
2102
2103 return 0;
2104}
2105
2106static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
2107{
2108 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2109 struct s5p_jpeg_q_data *q_data = NULL;
2110
2111 q_data = get_q_data(ctx, vb->vb2_queue->type);
2112 BUG_ON(q_data == NULL);
2113
2114 if (vb2_plane_size(vb, 0) < q_data->size) {
2115 pr_err("%s data will not fit into plane (%lu < %lu)\n",
2116 __func__, vb2_plane_size(vb, 0),
2117 (long)q_data->size);
2118 return -EINVAL;
2119 }
2120
2121 vb2_set_plane_payload(vb, 0, q_data->size);
2122
2123 return 0;
2124}
2125
2126static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
2127{
2128 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2129
2130 if (ctx->mode == S5P_JPEG_DECODE &&
2131 vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
2132 struct s5p_jpeg_q_data tmp, *q_data;
2133 ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
2134 (unsigned long)vb2_plane_vaddr(vb, 0),
2135 min((unsigned long)ctx->out_q.size,
Jacek Anaszewskif8433962013-11-21 13:33:09 -03002136 vb2_get_plane_payload(vb, 0)), ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002137 if (!ctx->hdr_parsed) {
2138 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
2139 return;
2140 }
2141
2142 q_data = &ctx->out_q;
2143 q_data->w = tmp.w;
2144 q_data->h = tmp.h;
2145
2146 q_data = &ctx->cap_q;
2147 q_data->w = tmp.w;
2148 q_data->h = tmp.h;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002149 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002150
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002151 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002152}
2153
2154static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
2155{
2156 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
2157 int ret;
2158
2159 ret = pm_runtime_get_sync(ctx->jpeg->dev);
2160
2161 return ret > 0 ? 0 : ret;
2162}
2163
Hans Verkuile37559b2014-04-17 02:47:21 -03002164static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002165{
2166 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
2167
2168 pm_runtime_put(ctx->jpeg->dev);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002169}
2170
2171static struct vb2_ops s5p_jpeg_qops = {
2172 .queue_setup = s5p_jpeg_queue_setup,
2173 .buf_prepare = s5p_jpeg_buf_prepare,
2174 .buf_queue = s5p_jpeg_buf_queue,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002175 .wait_prepare = vb2_ops_wait_prepare,
2176 .wait_finish = vb2_ops_wait_finish,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002177 .start_streaming = s5p_jpeg_start_streaming,
2178 .stop_streaming = s5p_jpeg_stop_streaming,
2179};
2180
2181static int queue_init(void *priv, struct vb2_queue *src_vq,
2182 struct vb2_queue *dst_vq)
2183{
2184 struct s5p_jpeg_ctx *ctx = priv;
2185 int ret;
2186
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002187 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2188 src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
2189 src_vq->drv_priv = ctx;
2190 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
2191 src_vq->ops = &s5p_jpeg_qops;
2192 src_vq->mem_ops = &vb2_dma_contig_memops;
Sakari Ailusade48682014-02-25 19:12:19 -03002193 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002194 src_vq->lock = &ctx->jpeg->lock;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002195
2196 ret = vb2_queue_init(src_vq);
2197 if (ret)
2198 return ret;
2199
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002200 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2201 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
2202 dst_vq->drv_priv = ctx;
2203 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
2204 dst_vq->ops = &s5p_jpeg_qops;
2205 dst_vq->mem_ops = &vb2_dma_contig_memops;
Sakari Ailusade48682014-02-25 19:12:19 -03002206 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002207 dst_vq->lock = &ctx->jpeg->lock;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002208
2209 return vb2_queue_init(dst_vq);
2210}
2211
2212/*
2213 * ============================================================================
2214 * ISR
2215 * ============================================================================
2216 */
2217
2218static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
2219{
2220 struct s5p_jpeg *jpeg = dev_id;
2221 struct s5p_jpeg_ctx *curr_ctx;
2222 struct vb2_buffer *src_buf, *dst_buf;
2223 unsigned long payload_size = 0;
2224 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
2225 bool enc_jpeg_too_large = false;
2226 bool timer_elapsed = false;
2227 bool op_completed = false;
2228
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002229 spin_lock(&jpeg->slock);
2230
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002231 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2232
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002233 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2234 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002235
2236 if (curr_ctx->mode == S5P_JPEG_ENCODE)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002237 enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);
2238 timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);
2239 op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002240 if (curr_ctx->mode == S5P_JPEG_DECODE)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002241 op_completed = op_completed &&
2242 s5p_jpeg_stream_stat_ok(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002243
2244 if (enc_jpeg_too_large) {
2245 state = VB2_BUF_STATE_ERROR;
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002246 s5p_jpeg_clear_enc_stream_stat(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002247 } else if (timer_elapsed) {
2248 state = VB2_BUF_STATE_ERROR;
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002249 s5p_jpeg_clear_timer_stat(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002250 } else if (!op_completed) {
2251 state = VB2_BUF_STATE_ERROR;
2252 } else {
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002253 payload_size = s5p_jpeg_compressed_size(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002254 }
2255
Kamil Debskiaca326a2013-04-24 10:08:02 -03002256 dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
2257 dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
Sakari Ailus309f4d62014-02-08 14:21:35 -03002258 dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
2259 dst_buf->v4l2_buf.flags |=
2260 src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
Kamil Debskiaca326a2013-04-24 10:08:02 -03002261
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002262 v4l2_m2m_buf_done(src_buf, state);
2263 if (curr_ctx->mode == S5P_JPEG_ENCODE)
2264 vb2_set_plane_payload(dst_buf, 0, payload_size);
2265 v4l2_m2m_buf_done(dst_buf, state);
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002266 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002267
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002268 curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002269 spin_unlock(&jpeg->slock);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03002270
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002271 s5p_jpeg_clear_int(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002272
2273 return IRQ_HANDLED;
2274}
2275
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002276static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
2277{
2278 unsigned int int_status;
2279 struct vb2_buffer *src_vb, *dst_vb;
2280 struct s5p_jpeg *jpeg = priv;
2281 struct s5p_jpeg_ctx *curr_ctx;
2282 unsigned long payload_size = 0;
2283
2284 spin_lock(&jpeg->slock);
2285
2286 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2287
2288 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2289 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2290
2291 int_status = exynos4_jpeg_get_int_status(jpeg->regs);
2292
2293 if (int_status) {
2294 switch (int_status & 0x1f) {
2295 case 0x1:
2296 jpeg->irq_ret = ERR_PROT;
2297 break;
2298 case 0x2:
2299 jpeg->irq_ret = OK_ENC_OR_DEC;
2300 break;
2301 case 0x4:
2302 jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;
2303 break;
2304 case 0x8:
2305 jpeg->irq_ret = ERR_MULTI_SCAN;
2306 break;
2307 case 0x10:
2308 jpeg->irq_ret = ERR_FRAME;
2309 break;
2310 default:
2311 jpeg->irq_ret = ERR_UNKNOWN;
2312 break;
2313 }
2314 } else {
2315 jpeg->irq_ret = ERR_UNKNOWN;
2316 }
2317
2318 if (jpeg->irq_ret == OK_ENC_OR_DEC) {
2319 if (curr_ctx->mode == S5P_JPEG_ENCODE) {
2320 payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
2321 vb2_set_plane_payload(dst_vb, 0, payload_size);
2322 }
2323 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
2324 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
2325 } else {
2326 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
2327 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
2328 }
2329
2330 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
2331 curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
2332
2333 spin_unlock(&jpeg->slock);
2334 return IRQ_HANDLED;
2335}
2336
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002337static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
2338{
2339 struct s5p_jpeg *jpeg = dev_id;
2340 struct s5p_jpeg_ctx *curr_ctx;
2341 struct vb2_buffer *src_buf, *dst_buf;
2342 unsigned long payload_size = 0;
2343 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
2344 bool interrupt_timeout = false;
2345 u32 irq_status;
2346
2347 spin_lock(&jpeg->slock);
2348
2349 irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);
2350 if (irq_status & EXYNOS3250_TIMER_INT_STAT) {
2351 exynos3250_jpeg_clear_timer_status(jpeg->regs);
2352 interrupt_timeout = true;
2353 dev_err(jpeg->dev, "Interrupt timeout occurred.\n");
2354 }
2355
2356 irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);
2357 exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);
2358
2359 jpeg->irq_status |= irq_status;
2360
2361 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2362
2363 if (!curr_ctx)
2364 goto exit_unlock;
2365
2366 if ((irq_status & EXYNOS3250_HEADER_STAT) &&
2367 (curr_ctx->mode == S5P_JPEG_DECODE)) {
2368 exynos3250_jpeg_rstart(jpeg->regs);
2369 goto exit_unlock;
2370 }
2371
2372 if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |
2373 EXYNOS3250_WDMA_DONE |
2374 EXYNOS3250_RDMA_DONE |
2375 EXYNOS3250_RESULT_STAT))
2376 payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);
2377 else if (interrupt_timeout)
2378 state = VB2_BUF_STATE_ERROR;
2379 else
2380 goto exit_unlock;
2381
2382 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2383 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2384
2385 dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
2386 dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
2387
2388 v4l2_m2m_buf_done(src_buf, state);
2389 if (curr_ctx->mode == S5P_JPEG_ENCODE)
2390 vb2_set_plane_payload(dst_buf, 0, payload_size);
2391 v4l2_m2m_buf_done(dst_buf, state);
2392 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
2393
2394 curr_ctx->subsampling =
2395 exynos3250_jpeg_get_subsampling_mode(jpeg->regs);
2396exit_unlock:
2397 spin_unlock(&jpeg->slock);
2398 return IRQ_HANDLED;
2399}
2400
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002401static void *jpeg_get_drv_data(struct device *dev);
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002402
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002403/*
2404 * ============================================================================
2405 * Driver basic infrastructure
2406 * ============================================================================
2407 */
2408
2409static int s5p_jpeg_probe(struct platform_device *pdev)
2410{
2411 struct s5p_jpeg *jpeg;
2412 struct resource *res;
2413 int ret;
2414
2415 /* JPEG IP abstraction struct */
Sachin Kamat5b58b952012-05-14 06:33:34 -03002416 jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002417 if (!jpeg)
2418 return -ENOMEM;
2419
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002420 jpeg->variant = jpeg_get_drv_data(&pdev->dev);
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002421
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002422 mutex_init(&jpeg->lock);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002423 spin_lock_init(&jpeg->slock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002424 jpeg->dev = &pdev->dev;
2425
2426 /* memory-mapped registers */
2427 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002428
Thierry Redingf23999e2013-01-21 06:09:07 -03002429 jpeg->regs = devm_ioremap_resource(&pdev->dev, res);
2430 if (IS_ERR(jpeg->regs))
2431 return PTR_ERR(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002432
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002433 /* interrupt service routine registration */
2434 jpeg->irq = ret = platform_get_irq(pdev, 0);
2435 if (ret < 0) {
2436 dev_err(&pdev->dev, "cannot find IRQ\n");
Sachin Kamat5b58b952012-05-14 06:33:34 -03002437 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002438 }
2439
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002440 ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,
2441 0, dev_name(&pdev->dev), jpeg);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002442 if (ret) {
2443 dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
Sachin Kamat5b58b952012-05-14 06:33:34 -03002444 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002445 }
2446
2447 /* clocks */
2448 jpeg->clk = clk_get(&pdev->dev, "jpeg");
2449 if (IS_ERR(jpeg->clk)) {
2450 dev_err(&pdev->dev, "cannot get clock\n");
2451 ret = PTR_ERR(jpeg->clk);
Sachin Kamat5b58b952012-05-14 06:33:34 -03002452 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002453 }
2454 dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002455
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002456 jpeg->sclk = clk_get(&pdev->dev, "sclk");
2457 if (IS_ERR(jpeg->sclk))
2458 dev_info(&pdev->dev, "sclk clock not available\n");
2459
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002460 /* v4l2 device */
2461 ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
2462 if (ret) {
2463 dev_err(&pdev->dev, "Failed to register v4l2 device\n");
2464 goto clk_get_rollback;
2465 }
2466
2467 /* mem2mem device */
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002468 jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002469 if (IS_ERR(jpeg->m2m_dev)) {
2470 v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
2471 ret = PTR_ERR(jpeg->m2m_dev);
2472 goto device_register_rollback;
2473 }
2474
2475 jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
2476 if (IS_ERR(jpeg->alloc_ctx)) {
2477 v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
2478 ret = PTR_ERR(jpeg->alloc_ctx);
2479 goto m2m_init_rollback;
2480 }
2481
2482 /* JPEG encoder /dev/videoX node */
2483 jpeg->vfd_encoder = video_device_alloc();
2484 if (!jpeg->vfd_encoder) {
2485 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2486 ret = -ENOMEM;
2487 goto vb2_allocator_rollback;
2488 }
Seung-Woo Kimbaaf0462013-10-10 04:45:56 -03002489 snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),
2490 "%s-enc", S5P_JPEG_M2M_NAME);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002491 jpeg->vfd_encoder->fops = &s5p_jpeg_fops;
2492 jpeg->vfd_encoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2493 jpeg->vfd_encoder->minor = -1;
2494 jpeg->vfd_encoder->release = video_device_release;
2495 jpeg->vfd_encoder->lock = &jpeg->lock;
2496 jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev;
Hans Verkuil954f3402012-09-05 06:05:50 -03002497 jpeg->vfd_encoder->vfl_dir = VFL_DIR_M2M;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002498
2499 ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
2500 if (ret) {
2501 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
2502 goto enc_vdev_alloc_rollback;
2503 }
2504
2505 video_set_drvdata(jpeg->vfd_encoder, jpeg);
2506 v4l2_info(&jpeg->v4l2_dev,
2507 "encoder device registered as /dev/video%d\n",
2508 jpeg->vfd_encoder->num);
2509
2510 /* JPEG decoder /dev/videoX node */
2511 jpeg->vfd_decoder = video_device_alloc();
2512 if (!jpeg->vfd_decoder) {
2513 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2514 ret = -ENOMEM;
2515 goto enc_vdev_register_rollback;
2516 }
Seung-Woo Kimbaaf0462013-10-10 04:45:56 -03002517 snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),
2518 "%s-dec", S5P_JPEG_M2M_NAME);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002519 jpeg->vfd_decoder->fops = &s5p_jpeg_fops;
2520 jpeg->vfd_decoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2521 jpeg->vfd_decoder->minor = -1;
2522 jpeg->vfd_decoder->release = video_device_release;
2523 jpeg->vfd_decoder->lock = &jpeg->lock;
2524 jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev;
Jacek Anaszewski7f7d8fe2013-09-11 06:17:45 -03002525 jpeg->vfd_decoder->vfl_dir = VFL_DIR_M2M;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002526
2527 ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
2528 if (ret) {
2529 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
2530 goto dec_vdev_alloc_rollback;
2531 }
2532
2533 video_set_drvdata(jpeg->vfd_decoder, jpeg);
2534 v4l2_info(&jpeg->v4l2_dev,
2535 "decoder device registered as /dev/video%d\n",
2536 jpeg->vfd_decoder->num);
2537
2538 /* final statements & power management */
2539 platform_set_drvdata(pdev, jpeg);
2540
2541 pm_runtime_enable(&pdev->dev);
2542
2543 v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
2544
2545 return 0;
2546
2547dec_vdev_alloc_rollback:
2548 video_device_release(jpeg->vfd_decoder);
2549
2550enc_vdev_register_rollback:
2551 video_unregister_device(jpeg->vfd_encoder);
2552
2553enc_vdev_alloc_rollback:
2554 video_device_release(jpeg->vfd_encoder);
2555
2556vb2_allocator_rollback:
2557 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
2558
2559m2m_init_rollback:
2560 v4l2_m2m_release(jpeg->m2m_dev);
2561
2562device_register_rollback:
2563 v4l2_device_unregister(&jpeg->v4l2_dev);
2564
2565clk_get_rollback:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002566 clk_put(jpeg->clk);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002567 if (!IS_ERR(jpeg->sclk))
2568 clk_put(jpeg->sclk);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002569
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002570 return ret;
2571}
2572
2573static int s5p_jpeg_remove(struct platform_device *pdev)
2574{
2575 struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
2576
2577 pm_runtime_disable(jpeg->dev);
2578
2579 video_unregister_device(jpeg->vfd_decoder);
2580 video_device_release(jpeg->vfd_decoder);
2581 video_unregister_device(jpeg->vfd_encoder);
2582 video_device_release(jpeg->vfd_encoder);
2583 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
2584 v4l2_m2m_release(jpeg->m2m_dev);
2585 v4l2_device_unregister(&jpeg->v4l2_dev);
2586
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002587 if (!pm_runtime_status_suspended(&pdev->dev)) {
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002588 clk_disable_unprepare(jpeg->clk);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002589 if (!IS_ERR(jpeg->sclk))
2590 clk_disable_unprepare(jpeg->sclk);
2591 }
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002592
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002593 clk_put(jpeg->clk);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002594 if (!IS_ERR(jpeg->sclk))
2595 clk_put(jpeg->sclk);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002596
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002597 return 0;
2598}
2599
2600static int s5p_jpeg_runtime_suspend(struct device *dev)
2601{
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002602 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
2603
2604 clk_disable_unprepare(jpeg->clk);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002605 if (!IS_ERR(jpeg->sclk))
2606 clk_disable_unprepare(jpeg->sclk);
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002607
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002608 return 0;
2609}
2610
2611static int s5p_jpeg_runtime_resume(struct device *dev)
2612{
2613 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002614 unsigned long flags;
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002615 int ret;
2616
2617 ret = clk_prepare_enable(jpeg->clk);
2618 if (ret < 0)
2619 return ret;
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03002620
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002621 if (!IS_ERR(jpeg->sclk)) {
2622 ret = clk_prepare_enable(jpeg->sclk);
2623 if (ret < 0)
2624 return ret;
2625 }
2626
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002627 spin_lock_irqsave(&jpeg->slock, flags);
2628
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002629 /*
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002630 * JPEG IP allows storing two Huffman tables for each component.
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002631 * We fill table 0 for each component and do this here only
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002632 * for S5PC210 and Exynos3250 SoCs. Exynos4x12 SoC requires
2633 * programming its Huffman tables each time the encoding process
2634 * is initialized, and thus it is accomplished in the device_run
2635 * callback of m2m_ops.
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002636 */
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002637 if (jpeg->variant->version == SJPEG_S5P ||
2638 jpeg->variant->version == SJPEG_EXYNOS3250) {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002639 s5p_jpeg_set_hdctbl(jpeg->regs);
2640 s5p_jpeg_set_hdctblg(jpeg->regs);
2641 s5p_jpeg_set_hactbl(jpeg->regs);
2642 s5p_jpeg_set_hactblg(jpeg->regs);
2643 }
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03002644
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002645 spin_unlock_irqrestore(&jpeg->slock, flags);
2646
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002647 return 0;
2648}
2649
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002650static int s5p_jpeg_suspend(struct device *dev)
2651{
2652 if (pm_runtime_suspended(dev))
2653 return 0;
2654
2655 return s5p_jpeg_runtime_suspend(dev);
2656}
2657
2658static int s5p_jpeg_resume(struct device *dev)
2659{
2660 if (pm_runtime_suspended(dev))
2661 return 0;
2662
2663 return s5p_jpeg_runtime_resume(dev);
2664}
2665
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002666static const struct dev_pm_ops s5p_jpeg_pm_ops = {
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002667 SET_SYSTEM_SLEEP_PM_OPS(s5p_jpeg_suspend, s5p_jpeg_resume)
2668 SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume, NULL)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002669};
2670
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002671static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
2672 .version = SJPEG_S5P,
2673 .jpeg_irq = s5p_jpeg_irq,
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002674 .m2m_ops = &s5p_jpeg_m2m_ops,
Jacek Anaszewskib2451682014-04-10 04:32:11 -03002675 .fmt_ver_flag = SJPEG_FMT_FLAG_S5P,
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03002676};
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002677
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002678static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
2679 .version = SJPEG_EXYNOS3250,
2680 .jpeg_irq = exynos3250_jpeg_irq,
2681 .m2m_ops = &exynos3250_jpeg_m2m_ops,
2682 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250,
2683};
2684
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002685static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
2686 .version = SJPEG_EXYNOS4,
2687 .jpeg_irq = exynos4_jpeg_irq,
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002688 .m2m_ops = &exynos4_jpeg_m2m_ops,
Jacek Anaszewskib2451682014-04-10 04:32:11 -03002689 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002690};
2691
2692static const struct of_device_id samsung_jpeg_match[] = {
2693 {
2694 .compatible = "samsung,s5pv210-jpeg",
2695 .data = &s5p_jpeg_drvdata,
2696 }, {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002697 .compatible = "samsung,exynos3250-jpeg",
2698 .data = &exynos3250_jpeg_drvdata,
2699 }, {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002700 .compatible = "samsung,exynos4210-jpeg",
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002701 .data = &exynos4_jpeg_drvdata,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002702 }, {
2703 .compatible = "samsung,exynos4212-jpeg",
2704 .data = &exynos4_jpeg_drvdata,
2705 },
2706 {},
2707};
2708
2709MODULE_DEVICE_TABLE(of, samsung_jpeg_match);
2710
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002711static void *jpeg_get_drv_data(struct device *dev)
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002712{
2713 struct s5p_jpeg_variant *driver_data = NULL;
2714 const struct of_device_id *match;
2715
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002716 if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
2717 return &s5p_jpeg_drvdata;
2718
2719 match = of_match_node(samsung_jpeg_match, dev->of_node);
2720
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002721 if (match)
2722 driver_data = (struct s5p_jpeg_variant *)match->data;
2723
2724 return driver_data;
2725}
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03002726
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002727static struct platform_driver s5p_jpeg_driver = {
2728 .probe = s5p_jpeg_probe,
2729 .remove = s5p_jpeg_remove,
2730 .driver = {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002731 .of_match_table = of_match_ptr(samsung_jpeg_match),
2732 .owner = THIS_MODULE,
2733 .name = S5P_JPEG_M2M_NAME,
2734 .pm = &s5p_jpeg_pm_ops,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002735 },
2736};
2737
Sachin Kamat87e94292012-07-03 05:54:33 -03002738module_platform_driver(s5p_jpeg_driver);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002739
2740MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002741MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002742MODULE_DESCRIPTION("Samsung JPEG codec driver");
2743MODULE_LICENSE("GPL");