blob: a3f8862e60f0c47a2b36eb062796603261088a2c [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
1136static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
1137 unsigned int walign,
1138 u32 *h, unsigned int hmin, unsigned int hmax,
1139 unsigned int halign)
1140{
1141 int width, height, w_step, h_step;
1142
1143 width = *w;
1144 height = *h;
1145
1146 w_step = 1 << walign;
1147 h_step = 1 << halign;
1148 v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
1149
1150 if (*w < width && (*w + w_step) < wmax)
1151 *w += w_step;
1152 if (*h < height && (*h + h_step) < hmax)
1153 *h += h_step;
1154
1155}
1156
1157static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
1158 struct s5p_jpeg_ctx *ctx, int q_type)
1159{
1160 struct v4l2_pix_format *pix = &f->fmt.pix;
1161
1162 if (pix->field == V4L2_FIELD_ANY)
1163 pix->field = V4L2_FIELD_NONE;
1164 else if (pix->field != V4L2_FIELD_NONE)
1165 return -EINVAL;
1166
1167 /* V4L2 specification suggests the driver corrects the format struct
1168 * if any of the dimensions is unsupported */
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001169 if (q_type == FMT_TYPE_OUTPUT)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001170 jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
1171 S5P_JPEG_MAX_WIDTH, 0,
1172 &pix->height, S5P_JPEG_MIN_HEIGHT,
1173 S5P_JPEG_MAX_HEIGHT, 0);
1174 else
1175 jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
1176 S5P_JPEG_MAX_WIDTH, fmt->h_align,
1177 &pix->height, S5P_JPEG_MIN_HEIGHT,
1178 S5P_JPEG_MAX_HEIGHT, fmt->v_align);
1179
1180 if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
1181 if (pix->sizeimage <= 0)
1182 pix->sizeimage = PAGE_SIZE;
1183 pix->bytesperline = 0;
1184 } else {
1185 u32 bpl = pix->bytesperline;
1186
1187 if (fmt->colplanes > 1 && bpl < pix->width)
1188 bpl = pix->width; /* planar */
1189
1190 if (fmt->colplanes == 1 && /* packed */
Jacek Anaszewskicc690902013-11-25 06:58:10 -03001191 (bpl << 3) / fmt->depth < pix->width)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001192 bpl = (pix->width * fmt->depth) >> 3;
1193
1194 pix->bytesperline = bpl;
1195 pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
1196 }
1197
1198 return 0;
1199}
1200
1201static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
1202 struct v4l2_format *f)
1203{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001204 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001205 struct v4l2_pix_format *pix = &f->fmt.pix;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001206 struct s5p_jpeg_fmt *fmt;
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001207 int ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001208
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001209 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1210 FMT_TYPE_CAPTURE);
1211 if (!fmt) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001212 v4l2_err(&ctx->jpeg->v4l2_dev,
1213 "Fourcc format (0x%08x) invalid.\n",
1214 f->fmt.pix.pixelformat);
1215 return -EINVAL;
1216 }
1217
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001218 if ((ctx->jpeg->variant->version != SJPEG_EXYNOS4) ||
1219 (ctx->mode != S5P_JPEG_DECODE))
1220 goto exit;
1221
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001222 /*
1223 * The exynos4x12 device requires resulting YUV image
1224 * subsampling not to be lower than the input jpeg subsampling.
1225 * If this requirement is not met then downgrade the requested
1226 * capture format to the one with subsampling equal to the input jpeg.
1227 */
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001228 if ((fmt->flags & SJPEG_FMT_NON_RGB) &&
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001229 (fmt->subsampling < ctx->subsampling)) {
1230 ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
1231 fmt->fourcc,
1232 &pix->pixelformat,
1233 ctx);
1234 if (ret < 0)
1235 pix->pixelformat = V4L2_PIX_FMT_GREY;
1236
1237 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1238 FMT_TYPE_CAPTURE);
1239 }
1240
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001241 /*
1242 * Decompression of a JPEG file with 4:2:0 subsampling and odd
1243 * width to the YUV 4:2:0 compliant formats produces a raw image
1244 * with broken luma component. Adjust capture format to RGB565
1245 * in such a case.
1246 */
1247 if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
1248 (ctx->out_q.w & 1) &&
1249 (pix->pixelformat == V4L2_PIX_FMT_NV12 ||
1250 pix->pixelformat == V4L2_PIX_FMT_NV21 ||
1251 pix->pixelformat == V4L2_PIX_FMT_YUV420)) {
1252 pix->pixelformat = V4L2_PIX_FMT_RGB565;
1253 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1254 FMT_TYPE_CAPTURE);
1255 }
1256
1257exit:
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001258 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001259}
1260
1261static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
1262 struct v4l2_format *f)
1263{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001264 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001265 struct s5p_jpeg_fmt *fmt;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001266
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001267 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1268 FMT_TYPE_OUTPUT);
1269 if (!fmt) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001270 v4l2_err(&ctx->jpeg->v4l2_dev,
1271 "Fourcc format (0x%08x) invalid.\n",
1272 f->fmt.pix.pixelformat);
1273 return -EINVAL;
1274 }
1275
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001276 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001277}
1278
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001279static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
1280 struct v4l2_format *f,
1281 int fmt_depth)
1282{
1283 struct v4l2_pix_format *pix = &f->fmt.pix;
1284 u32 pix_fmt = f->fmt.pix.pixelformat;
1285 int w = pix->width, h = pix->height, wh_align;
1286
1287 if (pix_fmt == V4L2_PIX_FMT_RGB32 ||
1288 pix_fmt == V4L2_PIX_FMT_NV24 ||
1289 pix_fmt == V4L2_PIX_FMT_NV42 ||
1290 pix_fmt == V4L2_PIX_FMT_NV12 ||
1291 pix_fmt == V4L2_PIX_FMT_NV21 ||
1292 pix_fmt == V4L2_PIX_FMT_YUV420)
1293 wh_align = 4;
1294 else
1295 wh_align = 1;
1296
1297 jpeg_bound_align_image(&w, S5P_JPEG_MIN_WIDTH,
1298 S5P_JPEG_MAX_WIDTH, wh_align,
1299 &h, S5P_JPEG_MIN_HEIGHT,
1300 S5P_JPEG_MAX_HEIGHT, wh_align);
1301
1302 return w * h * fmt_depth >> 3;
1303}
1304
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001305static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
1306{
1307 struct vb2_queue *vq;
1308 struct s5p_jpeg_q_data *q_data = NULL;
1309 struct v4l2_pix_format *pix = &f->fmt.pix;
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001310 struct v4l2_ctrl *ctrl_subs;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001311 unsigned int f_type;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001312
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001313 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001314 if (!vq)
1315 return -EINVAL;
1316
1317 q_data = get_q_data(ct, f->type);
1318 BUG_ON(q_data == NULL);
1319
1320 if (vb2_is_busy(vq)) {
1321 v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
1322 return -EBUSY;
1323 }
1324
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001325 f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
1326 FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;
1327
1328 q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001329 q_data->w = pix->width;
1330 q_data->h = pix->height;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001331 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
1332 /*
1333 * During encoding Exynos4x12 SoCs access wider memory area
1334 * than it results from Image_x and Image_y values written to
1335 * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu
1336 * page fault calculate proper buffer size in such a case.
1337 */
1338 if (ct->jpeg->variant->version == SJPEG_EXYNOS4 &&
1339 f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)
1340 q_data->size = exynos4_jpeg_get_output_buffer_size(ct,
1341 f,
1342 q_data->fmt->depth);
1343 else
1344 q_data->size = q_data->w * q_data->h *
1345 q_data->fmt->depth >> 3;
1346 } else {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001347 q_data->size = pix->sizeimage;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001348 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001349
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001350 if (f_type == FMT_TYPE_OUTPUT) {
1351 ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler,
1352 V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
1353 if (ctrl_subs)
1354 v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
1355 }
1356
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001357 return 0;
1358}
1359
1360static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
1361 struct v4l2_format *f)
1362{
1363 int ret;
1364
1365 ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
1366 if (ret)
1367 return ret;
1368
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001369 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001370}
1371
1372static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
1373 struct v4l2_format *f)
1374{
1375 int ret;
1376
1377 ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
1378 if (ret)
1379 return ret;
1380
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001381 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001382}
1383
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001384static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
1385 struct v4l2_rect *r)
1386{
1387 int w_ratio, h_ratio, scale_factor, cur_ratio, i;
1388
1389 w_ratio = ctx->out_q.w / r->width;
1390 h_ratio = ctx->out_q.h / r->height;
1391
1392 scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio;
1393 scale_factor = clamp_val(scale_factor, 1, 8);
1394
1395 /* Align scale ratio to the nearest power of 2 */
1396 for (i = 0; i <= 3; ++i) {
1397 cur_ratio = 1 << i;
1398 if (scale_factor <= cur_ratio) {
1399 ctx->scale_factor = cur_ratio;
1400 break;
1401 }
1402 }
1403
1404 r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);
1405 r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);
1406
1407 ctx->crop_rect.width = r->width;
1408 ctx->crop_rect.height = r->height;
1409 ctx->crop_rect.left = 0;
1410 ctx->crop_rect.top = 0;
1411
1412 ctx->crop_altered = true;
1413
1414 return 0;
1415}
1416
1417/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
1418static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
1419{
1420 if (a->left < b->left || a->top < b->top)
1421 return 0;
1422 if (a->left + a->width > b->left + b->width)
1423 return 0;
1424 if (a->top + a->height > b->top + b->height)
1425 return 0;
1426
1427 return 1;
1428}
1429
1430static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,
1431 struct v4l2_rect *r)
1432{
1433 struct v4l2_rect base_rect;
1434 int w_step, h_step;
1435
1436 switch (ctx->cap_q.fmt->fourcc) {
1437 case V4L2_PIX_FMT_NV12:
1438 case V4L2_PIX_FMT_NV21:
1439 w_step = 1;
1440 h_step = 2;
1441 break;
1442 case V4L2_PIX_FMT_YUV420:
1443 w_step = 2;
1444 h_step = 2;
1445 break;
1446 default:
1447 w_step = 1;
1448 h_step = 1;
1449 break;
1450 }
1451
1452 base_rect.top = 0;
1453 base_rect.left = 0;
1454 base_rect.width = ctx->out_q.w;
1455 base_rect.height = ctx->out_q.h;
1456
1457 r->width = round_down(r->width, w_step);
1458 r->height = round_down(r->height, h_step);
1459 r->left = round_down(r->left, 2);
1460 r->top = round_down(r->top, 2);
1461
1462 if (!enclosed_rectangle(r, &base_rect))
1463 return -EINVAL;
1464
1465 ctx->crop_rect.left = r->left;
1466 ctx->crop_rect.top = r->top;
1467 ctx->crop_rect.width = r->width;
1468 ctx->crop_rect.height = r->height;
1469
1470 ctx->crop_altered = true;
1471
1472 return 0;
1473}
1474
1475/*
1476 * V4L2 controls
1477 */
1478
Sachin Kamat9f3bd322012-05-10 03:38:40 -03001479static int s5p_jpeg_g_selection(struct file *file, void *priv,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001480 struct v4l2_selection *s)
1481{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001482 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001483
1484 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
Jacek Anaszewski38a6ef32014-04-10 04:32:15 -03001485 s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001486 return -EINVAL;
1487
1488 /* For JPEG blob active == default == bounds */
1489 switch (s->target) {
Sylwester Nawrockic1334822012-05-20 11:17:12 -03001490 case V4L2_SEL_TGT_CROP:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001491 case V4L2_SEL_TGT_CROP_BOUNDS:
1492 case V4L2_SEL_TGT_CROP_DEFAULT:
Sylwester Nawrockic1334822012-05-20 11:17:12 -03001493 case V4L2_SEL_TGT_COMPOSE:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001494 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1495 s->r.width = ctx->out_q.w;
1496 s->r.height = ctx->out_q.h;
1497 break;
1498 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1499 case V4L2_SEL_TGT_COMPOSE_PADDED:
1500 s->r.width = ctx->cap_q.w;
1501 s->r.height = ctx->cap_q.h;
1502 break;
1503 default:
1504 return -EINVAL;
1505 }
1506 s->r.left = 0;
1507 s->r.top = 0;
1508 return 0;
1509}
1510
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001511/*
1512 * V4L2 controls
1513 */
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001514static int s5p_jpeg_s_selection(struct file *file, void *fh,
1515 struct v4l2_selection *s)
1516{
1517 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
1518 struct v4l2_rect *rect = &s->r;
1519 int ret = -EINVAL;
1520
1521 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1522 return -EINVAL;
1523
1524 if (s->target == V4L2_SEL_TGT_COMPOSE) {
1525 if (ctx->mode != S5P_JPEG_DECODE)
1526 return -EINVAL;
1527 if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
1528 ret = exynos3250_jpeg_try_downscale(ctx, rect);
1529 } else if (s->target == V4L2_SEL_TGT_CROP) {
1530 if (ctx->mode != S5P_JPEG_ENCODE)
1531 return -EINVAL;
1532 if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
1533 ret = exynos3250_jpeg_try_crop(ctx, rect);
1534 }
1535
1536 return ret;
1537}
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001538
1539static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001540{
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001541 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1542 struct s5p_jpeg *jpeg = ctx->jpeg;
1543 unsigned long flags;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001544
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001545 switch (ctrl->id) {
1546 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1547 spin_lock_irqsave(&jpeg->slock, flags);
Jacek Anaszewski303b0a92013-12-18 11:14:00 -03001548 ctrl->val = s5p_jpeg_to_user_subsampling(ctx);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001549 spin_unlock_irqrestore(&jpeg->slock, flags);
1550 break;
1551 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001552
1553 return 0;
1554}
1555
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001556static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
1557{
1558 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1559 unsigned long flags;
1560 int ret = 0;
1561
1562 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1563
1564 if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING) {
1565 if (ctx->jpeg->variant->version == SJPEG_S5P)
1566 goto error_free;
1567 /*
1568 * The exynos4x12 device requires input raw image fourcc
1569 * to be V4L2_PIX_FMT_GREY if gray jpeg format
1570 * is to be set.
1571 */
1572 if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
1573 ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
1574 ret = -EINVAL;
1575 goto error_free;
1576 }
1577 /*
1578 * The exynos4x12 device requires resulting jpeg subsampling
1579 * not to be lower than the input raw image subsampling.
1580 */
1581 if (ctx->out_q.fmt->subsampling > ctrl->val)
1582 ctrl->val = ctx->out_q.fmt->subsampling;
1583 }
1584
1585error_free:
1586 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1587 return ret;
1588}
1589
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001590static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001591{
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001592 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1593 unsigned long flags;
1594
1595 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1596
1597 switch (ctrl->id) {
1598 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -03001599 ctx->compr_quality = ctrl->val;
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001600 break;
1601 case V4L2_CID_JPEG_RESTART_INTERVAL:
1602 ctx->restart_interval = ctrl->val;
1603 break;
1604 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1605 ctx->subsampling = ctrl->val;
1606 break;
1607 }
1608
1609 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1610 return 0;
1611}
1612
1613static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {
1614 .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl,
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001615 .try_ctrl = s5p_jpeg_try_ctrl,
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001616 .s_ctrl = s5p_jpeg_s_ctrl,
1617};
1618
1619static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)
1620{
1621 unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */
1622 struct v4l2_ctrl *ctrl;
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001623 int ret;
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001624
1625 v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
1626
1627 if (ctx->mode == S5P_JPEG_ENCODE) {
1628 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1629 V4L2_CID_JPEG_COMPRESSION_QUALITY,
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -03001630 0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001631
1632 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1633 V4L2_CID_JPEG_RESTART_INTERVAL,
1634 0, 3, 0xffff, 0);
Jacek Anaszewskifdf9e2b2013-11-21 13:33:41 -03001635 if (ctx->jpeg->variant->version == SJPEG_S5P)
1636 mask = ~0x06; /* 422, 420 */
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001637 }
1638
1639 ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1640 V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
1641 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,
1642 V4L2_JPEG_CHROMA_SUBSAMPLING_422);
1643
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001644 if (ctx->ctrl_handler.error) {
1645 ret = ctx->ctrl_handler.error;
1646 goto error_free;
1647 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001648
1649 if (ctx->mode == S5P_JPEG_DECODE)
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001650 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |
1651 V4L2_CTRL_FLAG_READ_ONLY;
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001652
1653 ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
1654 if (ret < 0)
1655 goto error_free;
1656
1657 return ret;
1658
1659error_free:
1660 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1661 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001662}
1663
1664static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
1665 .vidioc_querycap = s5p_jpeg_querycap,
1666
1667 .vidioc_enum_fmt_vid_cap = s5p_jpeg_enum_fmt_vid_cap,
1668 .vidioc_enum_fmt_vid_out = s5p_jpeg_enum_fmt_vid_out,
1669
1670 .vidioc_g_fmt_vid_cap = s5p_jpeg_g_fmt,
1671 .vidioc_g_fmt_vid_out = s5p_jpeg_g_fmt,
1672
1673 .vidioc_try_fmt_vid_cap = s5p_jpeg_try_fmt_vid_cap,
1674 .vidioc_try_fmt_vid_out = s5p_jpeg_try_fmt_vid_out,
1675
1676 .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap,
1677 .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out,
1678
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001679 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1680 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1681 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1682 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001683
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001684 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
1685 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001686
1687 .vidioc_g_selection = s5p_jpeg_g_selection,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001688 .vidioc_s_selection = s5p_jpeg_s_selection,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001689};
1690
1691/*
1692 * ============================================================================
1693 * mem2mem callbacks
1694 * ============================================================================
1695 */
1696
1697static void s5p_jpeg_device_run(void *priv)
1698{
1699 struct s5p_jpeg_ctx *ctx = priv;
1700 struct s5p_jpeg *jpeg = ctx->jpeg;
1701 struct vb2_buffer *src_buf, *dst_buf;
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03001702 unsigned long src_addr, dst_addr, flags;
1703
1704 spin_lock_irqsave(&ctx->jpeg->slock, flags);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001705
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001706 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1707 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001708 src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
1709 dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
1710
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001711 s5p_jpeg_reset(jpeg->regs);
1712 s5p_jpeg_poweron(jpeg->regs);
1713 s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001714 if (ctx->mode == S5P_JPEG_ENCODE) {
1715 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001716 s5p_jpeg_input_raw_mode(jpeg->regs,
1717 S5P_JPEG_RAW_IN_565);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001718 else
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001719 s5p_jpeg_input_raw_mode(jpeg->regs,
1720 S5P_JPEG_RAW_IN_422);
1721 s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
1722 s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);
1723 s5p_jpeg_x(jpeg->regs, ctx->out_q.w);
1724 s5p_jpeg_y(jpeg->regs, ctx->out_q.h);
1725 s5p_jpeg_imgadr(jpeg->regs, src_addr);
1726 s5p_jpeg_jpgadr(jpeg->regs, dst_addr);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001727
1728 /* ultimately comes from sizeimage from userspace */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001729 s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001730
1731 /* JPEG RGB to YCbCr conversion matrix */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001732 s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
1733 s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
1734 s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
1735 s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
1736 s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
1737 s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
1738 s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
1739 s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
1740 s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001741
1742 /*
1743 * JPEG IP allows storing 4 quantization tables
1744 * We fill table 0 for luma and table 1 for chroma
1745 */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03001746 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1747 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001748 /* use table 0 for Y */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001749 s5p_jpeg_qtbl(jpeg->regs, 1, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001750 /* use table 1 for Cb and Cr*/
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001751 s5p_jpeg_qtbl(jpeg->regs, 2, 1);
1752 s5p_jpeg_qtbl(jpeg->regs, 3, 1);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001753
1754 /* Y, Cb, Cr use Huffman table 0 */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001755 s5p_jpeg_htbl_ac(jpeg->regs, 1);
1756 s5p_jpeg_htbl_dc(jpeg->regs, 1);
1757 s5p_jpeg_htbl_ac(jpeg->regs, 2);
1758 s5p_jpeg_htbl_dc(jpeg->regs, 2);
1759 s5p_jpeg_htbl_ac(jpeg->regs, 3);
1760 s5p_jpeg_htbl_dc(jpeg->regs, 3);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001761 } else { /* S5P_JPEG_DECODE */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001762 s5p_jpeg_rst_int_enable(jpeg->regs, true);
1763 s5p_jpeg_data_num_int_enable(jpeg->regs, true);
1764 s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001765 if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001766 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001767 else
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001768 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
1769 s5p_jpeg_jpgadr(jpeg->regs, src_addr);
1770 s5p_jpeg_imgadr(jpeg->regs, dst_addr);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001771 }
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001772
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001773 s5p_jpeg_start(jpeg->regs);
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03001774
1775 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001776}
1777
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001778static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
1779{
1780 struct s5p_jpeg *jpeg = ctx->jpeg;
1781 struct s5p_jpeg_fmt *fmt;
1782 struct vb2_buffer *vb;
1783 struct s5p_jpeg_addr jpeg_addr;
1784 u32 pix_size, padding_bytes = 0;
1785
1786 pix_size = ctx->cap_q.w * ctx->cap_q.h;
1787
1788 if (ctx->mode == S5P_JPEG_ENCODE) {
1789 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1790 fmt = ctx->out_q.fmt;
1791 if (ctx->out_q.w % 2 && fmt->h_align > 0)
1792 padding_bytes = ctx->out_q.h;
1793 } else {
1794 fmt = ctx->cap_q.fmt;
1795 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1796 }
1797
1798 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
1799
1800 if (fmt->colplanes == 2) {
1801 jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;
1802 } else if (fmt->colplanes == 3) {
1803 jpeg_addr.cb = jpeg_addr.y + pix_size;
1804 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
1805 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
1806 else
1807 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
1808 }
1809
1810 exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);
1811}
1812
1813static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
1814{
1815 struct s5p_jpeg *jpeg = ctx->jpeg;
1816 struct vb2_buffer *vb;
1817 unsigned int jpeg_addr = 0;
1818
1819 if (ctx->mode == S5P_JPEG_ENCODE)
1820 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1821 else
1822 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1823
1824 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1825 exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
1826}
1827
1828static void exynos4_jpeg_device_run(void *priv)
1829{
1830 struct s5p_jpeg_ctx *ctx = priv;
1831 struct s5p_jpeg *jpeg = ctx->jpeg;
1832 unsigned int bitstream_size;
1833 unsigned long flags;
1834
1835 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1836
1837 if (ctx->mode == S5P_JPEG_ENCODE) {
1838 exynos4_jpeg_sw_reset(jpeg->regs);
1839 exynos4_jpeg_set_interrupt(jpeg->regs);
1840 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
1841
1842 exynos4_jpeg_set_huff_tbl(jpeg->regs);
1843
1844 /*
1845 * JPEG IP allows storing 4 quantization tables
1846 * We fill table 0 for luma and table 1 for chroma
1847 */
1848 exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1849 exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
1850
1851 exynos4_jpeg_set_encode_tbl_select(jpeg->regs,
1852 ctx->compr_quality);
1853 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
1854 ctx->cap_q.h);
1855
1856 exynos4_jpeg_set_enc_out_fmt(jpeg->regs, ctx->subsampling);
1857 exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->out_q.fmt->fourcc);
1858 exynos4_jpeg_set_img_addr(ctx);
1859 exynos4_jpeg_set_jpeg_addr(ctx);
1860 exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
1861 ctx->out_q.fmt->fourcc);
1862 } else {
1863 exynos4_jpeg_sw_reset(jpeg->regs);
1864 exynos4_jpeg_set_interrupt(jpeg->regs);
1865 exynos4_jpeg_set_img_addr(ctx);
1866 exynos4_jpeg_set_jpeg_addr(ctx);
1867 exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->cap_q.fmt->fourcc);
1868
1869 bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
1870
1871 exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
1872 }
1873
1874 exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
1875
1876 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1877}
1878
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001879static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
1880{
1881 struct s5p_jpeg *jpeg = ctx->jpeg;
1882 struct s5p_jpeg_fmt *fmt;
1883 struct vb2_buffer *vb;
1884 struct s5p_jpeg_addr jpeg_addr;
1885 u32 pix_size;
1886
1887 pix_size = ctx->cap_q.w * ctx->cap_q.h;
1888
1889 if (ctx->mode == S5P_JPEG_ENCODE) {
1890 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1891 fmt = ctx->out_q.fmt;
1892 } else {
1893 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1894 fmt = ctx->cap_q.fmt;
1895 }
1896
1897 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
1898
1899 if (fmt->colplanes == 2) {
1900 jpeg_addr.cb = jpeg_addr.y + pix_size;
1901 } else if (fmt->colplanes == 3) {
1902 jpeg_addr.cb = jpeg_addr.y + pix_size;
1903 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
1904 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
1905 else
1906 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
1907 }
1908
1909 exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);
1910}
1911
1912static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
1913{
1914 struct s5p_jpeg *jpeg = ctx->jpeg;
1915 struct vb2_buffer *vb;
1916 unsigned int jpeg_addr = 0;
1917
1918 if (ctx->mode == S5P_JPEG_ENCODE)
1919 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1920 else
1921 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1922
1923 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1924 exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);
1925}
1926
1927static void exynos3250_jpeg_device_run(void *priv)
1928{
1929 struct s5p_jpeg_ctx *ctx = priv;
1930 struct s5p_jpeg *jpeg = ctx->jpeg;
1931 unsigned long flags;
1932
1933 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1934
1935 exynos3250_jpeg_reset(jpeg->regs);
1936 exynos3250_jpeg_set_dma_num(jpeg->regs);
1937 exynos3250_jpeg_poweron(jpeg->regs);
1938 exynos3250_jpeg_clk_set(jpeg->regs);
1939 exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);
1940
1941 if (ctx->mode == S5P_JPEG_ENCODE) {
1942 exynos3250_jpeg_input_raw_fmt(jpeg->regs,
1943 ctx->out_q.fmt->fourcc);
1944 exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);
1945
1946 /*
1947 * JPEG IP allows storing 4 quantization tables
1948 * We fill table 0 for luma and table 1 for chroma
1949 */
1950 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1951 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
1952 /* use table 0 for Y */
1953 exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);
1954 /* use table 1 for Cb and Cr*/
1955 exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
1956 exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
1957
1958 /* Y, Cb, Cr use Huffman table 0 */
1959 exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
1960 exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
1961 exynos3250_jpeg_htbl_ac(jpeg->regs, 2);
1962 exynos3250_jpeg_htbl_dc(jpeg->regs, 2);
1963 exynos3250_jpeg_htbl_ac(jpeg->regs, 3);
1964 exynos3250_jpeg_htbl_dc(jpeg->regs, 3);
1965
1966 exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);
1967 exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);
1968 exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,
1969 ctx->out_q.w);
1970 exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,
1971 ctx->crop_rect.top);
1972 exynos3250_jpeg_set_img_addr(ctx);
1973 exynos3250_jpeg_set_jpeg_addr(ctx);
1974 exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
1975
1976 /* ultimately comes from sizeimage from userspace */
1977 exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);
1978
1979 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||
1980 ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||
1981 ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
1982 exynos3250_jpeg_set_y16(jpeg->regs, true);
1983 } else {
1984 exynos3250_jpeg_set_img_addr(ctx);
1985 exynos3250_jpeg_set_jpeg_addr(ctx);
1986 exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,
1987 ctx->cap_q.w);
1988 exynos3250_jpeg_offset(jpeg->regs, 0, 0);
1989 exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,
1990 ctx->scale_factor);
1991 exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);
1992 exynos3250_jpeg_output_raw_fmt(jpeg->regs,
1993 ctx->cap_q.fmt->fourcc);
1994 }
1995
1996 exynos3250_jpeg_interrupts_enable(jpeg->regs);
1997
1998 /* JPEG RGB to YCbCr conversion matrix */
1999 exynos3250_jpeg_coef(jpeg->regs, ctx->mode);
2000
2001 exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);
2002 jpeg->irq_status = 0;
2003 exynos3250_jpeg_start(jpeg->regs);
2004
2005 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
2006}
2007
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002008static int s5p_jpeg_job_ready(void *priv)
2009{
2010 struct s5p_jpeg_ctx *ctx = priv;
2011
2012 if (ctx->mode == S5P_JPEG_DECODE)
2013 return ctx->hdr_parsed;
2014 return 1;
2015}
2016
2017static void s5p_jpeg_job_abort(void *priv)
2018{
2019}
2020
2021static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
2022 .device_run = s5p_jpeg_device_run,
2023 .job_ready = s5p_jpeg_job_ready,
2024 .job_abort = s5p_jpeg_job_abort,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002025};
2026
2027static struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {
2028 .device_run = exynos3250_jpeg_device_run,
2029 .job_ready = s5p_jpeg_job_ready,
2030 .job_abort = s5p_jpeg_job_abort,
2031};
2032
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002033static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002034 .device_run = exynos4_jpeg_device_run,
2035 .job_ready = s5p_jpeg_job_ready,
2036 .job_abort = s5p_jpeg_job_abort,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002037};
2038
2039/*
2040 * ============================================================================
2041 * Queue operations
2042 * ============================================================================
2043 */
2044
Marek Szyprowski719c1742012-01-13 05:12:38 -03002045static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
2046 const struct v4l2_format *fmt,
2047 unsigned int *nbuffers, unsigned int *nplanes,
2048 unsigned int sizes[], void *alloc_ctxs[])
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002049{
2050 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
2051 struct s5p_jpeg_q_data *q_data = NULL;
2052 unsigned int size, count = *nbuffers;
2053
2054 q_data = get_q_data(ctx, vq->type);
2055 BUG_ON(q_data == NULL);
2056
2057 size = q_data->size;
2058
2059 /*
2060 * header is parsed during decoding and parsed information stored
2061 * in the context so we do not allow another buffer to overwrite it
2062 */
2063 if (ctx->mode == S5P_JPEG_DECODE)
2064 count = 1;
2065
2066 *nbuffers = count;
2067 *nplanes = 1;
2068 sizes[0] = size;
2069 alloc_ctxs[0] = ctx->jpeg->alloc_ctx;
2070
2071 return 0;
2072}
2073
2074static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
2075{
2076 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2077 struct s5p_jpeg_q_data *q_data = NULL;
2078
2079 q_data = get_q_data(ctx, vb->vb2_queue->type);
2080 BUG_ON(q_data == NULL);
2081
2082 if (vb2_plane_size(vb, 0) < q_data->size) {
2083 pr_err("%s data will not fit into plane (%lu < %lu)\n",
2084 __func__, vb2_plane_size(vb, 0),
2085 (long)q_data->size);
2086 return -EINVAL;
2087 }
2088
2089 vb2_set_plane_payload(vb, 0, q_data->size);
2090
2091 return 0;
2092}
2093
2094static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
2095{
2096 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2097
2098 if (ctx->mode == S5P_JPEG_DECODE &&
2099 vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
2100 struct s5p_jpeg_q_data tmp, *q_data;
2101 ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
2102 (unsigned long)vb2_plane_vaddr(vb, 0),
2103 min((unsigned long)ctx->out_q.size,
Jacek Anaszewskif8433962013-11-21 13:33:09 -03002104 vb2_get_plane_payload(vb, 0)), ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002105 if (!ctx->hdr_parsed) {
2106 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
2107 return;
2108 }
2109
2110 q_data = &ctx->out_q;
2111 q_data->w = tmp.w;
2112 q_data->h = tmp.h;
2113
2114 q_data = &ctx->cap_q;
2115 q_data->w = tmp.w;
2116 q_data->h = tmp.h;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002117 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002118
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002119 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002120}
2121
2122static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
2123{
2124 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
2125 int ret;
2126
2127 ret = pm_runtime_get_sync(ctx->jpeg->dev);
2128
2129 return ret > 0 ? 0 : ret;
2130}
2131
Hans Verkuile37559b2014-04-17 02:47:21 -03002132static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002133{
2134 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
2135
2136 pm_runtime_put(ctx->jpeg->dev);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002137}
2138
2139static struct vb2_ops s5p_jpeg_qops = {
2140 .queue_setup = s5p_jpeg_queue_setup,
2141 .buf_prepare = s5p_jpeg_buf_prepare,
2142 .buf_queue = s5p_jpeg_buf_queue,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002143 .wait_prepare = vb2_ops_wait_prepare,
2144 .wait_finish = vb2_ops_wait_finish,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002145 .start_streaming = s5p_jpeg_start_streaming,
2146 .stop_streaming = s5p_jpeg_stop_streaming,
2147};
2148
2149static int queue_init(void *priv, struct vb2_queue *src_vq,
2150 struct vb2_queue *dst_vq)
2151{
2152 struct s5p_jpeg_ctx *ctx = priv;
2153 int ret;
2154
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002155 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2156 src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
2157 src_vq->drv_priv = ctx;
2158 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
2159 src_vq->ops = &s5p_jpeg_qops;
2160 src_vq->mem_ops = &vb2_dma_contig_memops;
Sakari Ailusade48682014-02-25 19:12:19 -03002161 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002162 src_vq->lock = &ctx->jpeg->lock;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002163
2164 ret = vb2_queue_init(src_vq);
2165 if (ret)
2166 return ret;
2167
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002168 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2169 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
2170 dst_vq->drv_priv = ctx;
2171 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
2172 dst_vq->ops = &s5p_jpeg_qops;
2173 dst_vq->mem_ops = &vb2_dma_contig_memops;
Sakari Ailusade48682014-02-25 19:12:19 -03002174 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002175 dst_vq->lock = &ctx->jpeg->lock;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002176
2177 return vb2_queue_init(dst_vq);
2178}
2179
2180/*
2181 * ============================================================================
2182 * ISR
2183 * ============================================================================
2184 */
2185
2186static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
2187{
2188 struct s5p_jpeg *jpeg = dev_id;
2189 struct s5p_jpeg_ctx *curr_ctx;
2190 struct vb2_buffer *src_buf, *dst_buf;
2191 unsigned long payload_size = 0;
2192 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
2193 bool enc_jpeg_too_large = false;
2194 bool timer_elapsed = false;
2195 bool op_completed = false;
2196
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002197 spin_lock(&jpeg->slock);
2198
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002199 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2200
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002201 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2202 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002203
2204 if (curr_ctx->mode == S5P_JPEG_ENCODE)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002205 enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);
2206 timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);
2207 op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002208 if (curr_ctx->mode == S5P_JPEG_DECODE)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002209 op_completed = op_completed &&
2210 s5p_jpeg_stream_stat_ok(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002211
2212 if (enc_jpeg_too_large) {
2213 state = VB2_BUF_STATE_ERROR;
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002214 s5p_jpeg_clear_enc_stream_stat(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002215 } else if (timer_elapsed) {
2216 state = VB2_BUF_STATE_ERROR;
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002217 s5p_jpeg_clear_timer_stat(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002218 } else if (!op_completed) {
2219 state = VB2_BUF_STATE_ERROR;
2220 } else {
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002221 payload_size = s5p_jpeg_compressed_size(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002222 }
2223
Kamil Debskiaca326a2013-04-24 10:08:02 -03002224 dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
2225 dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
Sakari Ailus309f4d62014-02-08 14:21:35 -03002226 dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
2227 dst_buf->v4l2_buf.flags |=
2228 src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
Kamil Debskiaca326a2013-04-24 10:08:02 -03002229
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002230 v4l2_m2m_buf_done(src_buf, state);
2231 if (curr_ctx->mode == S5P_JPEG_ENCODE)
2232 vb2_set_plane_payload(dst_buf, 0, payload_size);
2233 v4l2_m2m_buf_done(dst_buf, state);
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002234 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002235
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002236 curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002237 spin_unlock(&jpeg->slock);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03002238
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002239 s5p_jpeg_clear_int(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002240
2241 return IRQ_HANDLED;
2242}
2243
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002244static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
2245{
2246 unsigned int int_status;
2247 struct vb2_buffer *src_vb, *dst_vb;
2248 struct s5p_jpeg *jpeg = priv;
2249 struct s5p_jpeg_ctx *curr_ctx;
2250 unsigned long payload_size = 0;
2251
2252 spin_lock(&jpeg->slock);
2253
2254 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2255
2256 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2257 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2258
2259 int_status = exynos4_jpeg_get_int_status(jpeg->regs);
2260
2261 if (int_status) {
2262 switch (int_status & 0x1f) {
2263 case 0x1:
2264 jpeg->irq_ret = ERR_PROT;
2265 break;
2266 case 0x2:
2267 jpeg->irq_ret = OK_ENC_OR_DEC;
2268 break;
2269 case 0x4:
2270 jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;
2271 break;
2272 case 0x8:
2273 jpeg->irq_ret = ERR_MULTI_SCAN;
2274 break;
2275 case 0x10:
2276 jpeg->irq_ret = ERR_FRAME;
2277 break;
2278 default:
2279 jpeg->irq_ret = ERR_UNKNOWN;
2280 break;
2281 }
2282 } else {
2283 jpeg->irq_ret = ERR_UNKNOWN;
2284 }
2285
2286 if (jpeg->irq_ret == OK_ENC_OR_DEC) {
2287 if (curr_ctx->mode == S5P_JPEG_ENCODE) {
2288 payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
2289 vb2_set_plane_payload(dst_vb, 0, payload_size);
2290 }
2291 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
2292 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
2293 } else {
2294 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
2295 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
2296 }
2297
2298 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
2299 curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
2300
2301 spin_unlock(&jpeg->slock);
2302 return IRQ_HANDLED;
2303}
2304
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002305static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
2306{
2307 struct s5p_jpeg *jpeg = dev_id;
2308 struct s5p_jpeg_ctx *curr_ctx;
2309 struct vb2_buffer *src_buf, *dst_buf;
2310 unsigned long payload_size = 0;
2311 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
2312 bool interrupt_timeout = false;
2313 u32 irq_status;
2314
2315 spin_lock(&jpeg->slock);
2316
2317 irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);
2318 if (irq_status & EXYNOS3250_TIMER_INT_STAT) {
2319 exynos3250_jpeg_clear_timer_status(jpeg->regs);
2320 interrupt_timeout = true;
2321 dev_err(jpeg->dev, "Interrupt timeout occurred.\n");
2322 }
2323
2324 irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);
2325 exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);
2326
2327 jpeg->irq_status |= irq_status;
2328
2329 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2330
2331 if (!curr_ctx)
2332 goto exit_unlock;
2333
2334 if ((irq_status & EXYNOS3250_HEADER_STAT) &&
2335 (curr_ctx->mode == S5P_JPEG_DECODE)) {
2336 exynos3250_jpeg_rstart(jpeg->regs);
2337 goto exit_unlock;
2338 }
2339
2340 if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |
2341 EXYNOS3250_WDMA_DONE |
2342 EXYNOS3250_RDMA_DONE |
2343 EXYNOS3250_RESULT_STAT))
2344 payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);
2345 else if (interrupt_timeout)
2346 state = VB2_BUF_STATE_ERROR;
2347 else
2348 goto exit_unlock;
2349
2350 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2351 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2352
2353 dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
2354 dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
2355
2356 v4l2_m2m_buf_done(src_buf, state);
2357 if (curr_ctx->mode == S5P_JPEG_ENCODE)
2358 vb2_set_plane_payload(dst_buf, 0, payload_size);
2359 v4l2_m2m_buf_done(dst_buf, state);
2360 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
2361
2362 curr_ctx->subsampling =
2363 exynos3250_jpeg_get_subsampling_mode(jpeg->regs);
2364exit_unlock:
2365 spin_unlock(&jpeg->slock);
2366 return IRQ_HANDLED;
2367}
2368
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002369static void *jpeg_get_drv_data(struct device *dev);
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002370
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002371/*
2372 * ============================================================================
2373 * Driver basic infrastructure
2374 * ============================================================================
2375 */
2376
2377static int s5p_jpeg_probe(struct platform_device *pdev)
2378{
2379 struct s5p_jpeg *jpeg;
2380 struct resource *res;
2381 int ret;
2382
2383 /* JPEG IP abstraction struct */
Sachin Kamat5b58b952012-05-14 06:33:34 -03002384 jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002385 if (!jpeg)
2386 return -ENOMEM;
2387
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002388 jpeg->variant = jpeg_get_drv_data(&pdev->dev);
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002389
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002390 mutex_init(&jpeg->lock);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002391 spin_lock_init(&jpeg->slock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002392 jpeg->dev = &pdev->dev;
2393
2394 /* memory-mapped registers */
2395 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002396
Thierry Redingf23999e2013-01-21 06:09:07 -03002397 jpeg->regs = devm_ioremap_resource(&pdev->dev, res);
2398 if (IS_ERR(jpeg->regs))
2399 return PTR_ERR(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002400
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002401 /* interrupt service routine registration */
2402 jpeg->irq = ret = platform_get_irq(pdev, 0);
2403 if (ret < 0) {
2404 dev_err(&pdev->dev, "cannot find IRQ\n");
Sachin Kamat5b58b952012-05-14 06:33:34 -03002405 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002406 }
2407
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002408 ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,
2409 0, dev_name(&pdev->dev), jpeg);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002410 if (ret) {
2411 dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
Sachin Kamat5b58b952012-05-14 06:33:34 -03002412 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002413 }
2414
2415 /* clocks */
2416 jpeg->clk = clk_get(&pdev->dev, "jpeg");
2417 if (IS_ERR(jpeg->clk)) {
2418 dev_err(&pdev->dev, "cannot get clock\n");
2419 ret = PTR_ERR(jpeg->clk);
Sachin Kamat5b58b952012-05-14 06:33:34 -03002420 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002421 }
2422 dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002423
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002424 jpeg->sclk = clk_get(&pdev->dev, "sclk");
2425 if (IS_ERR(jpeg->sclk))
2426 dev_info(&pdev->dev, "sclk clock not available\n");
2427
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002428 /* v4l2 device */
2429 ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
2430 if (ret) {
2431 dev_err(&pdev->dev, "Failed to register v4l2 device\n");
2432 goto clk_get_rollback;
2433 }
2434
2435 /* mem2mem device */
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002436 jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002437 if (IS_ERR(jpeg->m2m_dev)) {
2438 v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
2439 ret = PTR_ERR(jpeg->m2m_dev);
2440 goto device_register_rollback;
2441 }
2442
2443 jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
2444 if (IS_ERR(jpeg->alloc_ctx)) {
2445 v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
2446 ret = PTR_ERR(jpeg->alloc_ctx);
2447 goto m2m_init_rollback;
2448 }
2449
2450 /* JPEG encoder /dev/videoX node */
2451 jpeg->vfd_encoder = video_device_alloc();
2452 if (!jpeg->vfd_encoder) {
2453 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2454 ret = -ENOMEM;
2455 goto vb2_allocator_rollback;
2456 }
Seung-Woo Kimbaaf0462013-10-10 04:45:56 -03002457 snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),
2458 "%s-enc", S5P_JPEG_M2M_NAME);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002459 jpeg->vfd_encoder->fops = &s5p_jpeg_fops;
2460 jpeg->vfd_encoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2461 jpeg->vfd_encoder->minor = -1;
2462 jpeg->vfd_encoder->release = video_device_release;
2463 jpeg->vfd_encoder->lock = &jpeg->lock;
2464 jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev;
Hans Verkuil954f3402012-09-05 06:05:50 -03002465 jpeg->vfd_encoder->vfl_dir = VFL_DIR_M2M;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002466
2467 ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
2468 if (ret) {
2469 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
2470 goto enc_vdev_alloc_rollback;
2471 }
2472
2473 video_set_drvdata(jpeg->vfd_encoder, jpeg);
2474 v4l2_info(&jpeg->v4l2_dev,
2475 "encoder device registered as /dev/video%d\n",
2476 jpeg->vfd_encoder->num);
2477
2478 /* JPEG decoder /dev/videoX node */
2479 jpeg->vfd_decoder = video_device_alloc();
2480 if (!jpeg->vfd_decoder) {
2481 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2482 ret = -ENOMEM;
2483 goto enc_vdev_register_rollback;
2484 }
Seung-Woo Kimbaaf0462013-10-10 04:45:56 -03002485 snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),
2486 "%s-dec", S5P_JPEG_M2M_NAME);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002487 jpeg->vfd_decoder->fops = &s5p_jpeg_fops;
2488 jpeg->vfd_decoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2489 jpeg->vfd_decoder->minor = -1;
2490 jpeg->vfd_decoder->release = video_device_release;
2491 jpeg->vfd_decoder->lock = &jpeg->lock;
2492 jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev;
Jacek Anaszewski7f7d8fe2013-09-11 06:17:45 -03002493 jpeg->vfd_decoder->vfl_dir = VFL_DIR_M2M;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002494
2495 ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
2496 if (ret) {
2497 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
2498 goto dec_vdev_alloc_rollback;
2499 }
2500
2501 video_set_drvdata(jpeg->vfd_decoder, jpeg);
2502 v4l2_info(&jpeg->v4l2_dev,
2503 "decoder device registered as /dev/video%d\n",
2504 jpeg->vfd_decoder->num);
2505
2506 /* final statements & power management */
2507 platform_set_drvdata(pdev, jpeg);
2508
2509 pm_runtime_enable(&pdev->dev);
2510
2511 v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
2512
2513 return 0;
2514
2515dec_vdev_alloc_rollback:
2516 video_device_release(jpeg->vfd_decoder);
2517
2518enc_vdev_register_rollback:
2519 video_unregister_device(jpeg->vfd_encoder);
2520
2521enc_vdev_alloc_rollback:
2522 video_device_release(jpeg->vfd_encoder);
2523
2524vb2_allocator_rollback:
2525 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
2526
2527m2m_init_rollback:
2528 v4l2_m2m_release(jpeg->m2m_dev);
2529
2530device_register_rollback:
2531 v4l2_device_unregister(&jpeg->v4l2_dev);
2532
2533clk_get_rollback:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002534 clk_put(jpeg->clk);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002535 if (!IS_ERR(jpeg->sclk))
2536 clk_put(jpeg->sclk);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002537
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002538 return ret;
2539}
2540
2541static int s5p_jpeg_remove(struct platform_device *pdev)
2542{
2543 struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
2544
2545 pm_runtime_disable(jpeg->dev);
2546
2547 video_unregister_device(jpeg->vfd_decoder);
2548 video_device_release(jpeg->vfd_decoder);
2549 video_unregister_device(jpeg->vfd_encoder);
2550 video_device_release(jpeg->vfd_encoder);
2551 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
2552 v4l2_m2m_release(jpeg->m2m_dev);
2553 v4l2_device_unregister(&jpeg->v4l2_dev);
2554
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002555 if (!pm_runtime_status_suspended(&pdev->dev)) {
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002556 clk_disable_unprepare(jpeg->clk);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002557 if (!IS_ERR(jpeg->sclk))
2558 clk_disable_unprepare(jpeg->sclk);
2559 }
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002560
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002561 clk_put(jpeg->clk);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002562 if (!IS_ERR(jpeg->sclk))
2563 clk_put(jpeg->sclk);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002564
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002565 return 0;
2566}
2567
2568static int s5p_jpeg_runtime_suspend(struct device *dev)
2569{
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002570 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
2571
2572 clk_disable_unprepare(jpeg->clk);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002573 if (!IS_ERR(jpeg->sclk))
2574 clk_disable_unprepare(jpeg->sclk);
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002575
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002576 return 0;
2577}
2578
2579static int s5p_jpeg_runtime_resume(struct device *dev)
2580{
2581 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002582 unsigned long flags;
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002583 int ret;
2584
2585 ret = clk_prepare_enable(jpeg->clk);
2586 if (ret < 0)
2587 return ret;
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03002588
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002589 if (!IS_ERR(jpeg->sclk)) {
2590 ret = clk_prepare_enable(jpeg->sclk);
2591 if (ret < 0)
2592 return ret;
2593 }
2594
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002595 spin_lock_irqsave(&jpeg->slock, flags);
2596
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002597 /*
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002598 * JPEG IP allows storing two Huffman tables for each component.
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002599 * We fill table 0 for each component and do this here only
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002600 * for S5PC210 and Exynos3250 SoCs. Exynos4x12 SoC requires
2601 * programming its Huffman tables each time the encoding process
2602 * is initialized, and thus it is accomplished in the device_run
2603 * callback of m2m_ops.
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002604 */
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002605 if (jpeg->variant->version == SJPEG_S5P ||
2606 jpeg->variant->version == SJPEG_EXYNOS3250) {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002607 s5p_jpeg_set_hdctbl(jpeg->regs);
2608 s5p_jpeg_set_hdctblg(jpeg->regs);
2609 s5p_jpeg_set_hactbl(jpeg->regs);
2610 s5p_jpeg_set_hactblg(jpeg->regs);
2611 }
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03002612
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002613 spin_unlock_irqrestore(&jpeg->slock, flags);
2614
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002615 return 0;
2616}
2617
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002618static int s5p_jpeg_suspend(struct device *dev)
2619{
2620 if (pm_runtime_suspended(dev))
2621 return 0;
2622
2623 return s5p_jpeg_runtime_suspend(dev);
2624}
2625
2626static int s5p_jpeg_resume(struct device *dev)
2627{
2628 if (pm_runtime_suspended(dev))
2629 return 0;
2630
2631 return s5p_jpeg_runtime_resume(dev);
2632}
2633
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002634static const struct dev_pm_ops s5p_jpeg_pm_ops = {
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002635 SET_SYSTEM_SLEEP_PM_OPS(s5p_jpeg_suspend, s5p_jpeg_resume)
2636 SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume, NULL)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002637};
2638
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002639static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
2640 .version = SJPEG_S5P,
2641 .jpeg_irq = s5p_jpeg_irq,
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002642 .m2m_ops = &s5p_jpeg_m2m_ops,
Jacek Anaszewskib2451682014-04-10 04:32:11 -03002643 .fmt_ver_flag = SJPEG_FMT_FLAG_S5P,
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03002644};
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002645
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002646static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
2647 .version = SJPEG_EXYNOS3250,
2648 .jpeg_irq = exynos3250_jpeg_irq,
2649 .m2m_ops = &exynos3250_jpeg_m2m_ops,
2650 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250,
2651};
2652
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002653static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
2654 .version = SJPEG_EXYNOS4,
2655 .jpeg_irq = exynos4_jpeg_irq,
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002656 .m2m_ops = &exynos4_jpeg_m2m_ops,
Jacek Anaszewskib2451682014-04-10 04:32:11 -03002657 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002658};
2659
2660static const struct of_device_id samsung_jpeg_match[] = {
2661 {
2662 .compatible = "samsung,s5pv210-jpeg",
2663 .data = &s5p_jpeg_drvdata,
2664 }, {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002665 .compatible = "samsung,exynos3250-jpeg",
2666 .data = &exynos3250_jpeg_drvdata,
2667 }, {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002668 .compatible = "samsung,exynos4210-jpeg",
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002669 .data = &exynos4_jpeg_drvdata,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002670 }, {
2671 .compatible = "samsung,exynos4212-jpeg",
2672 .data = &exynos4_jpeg_drvdata,
2673 },
2674 {},
2675};
2676
2677MODULE_DEVICE_TABLE(of, samsung_jpeg_match);
2678
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002679static void *jpeg_get_drv_data(struct device *dev)
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002680{
2681 struct s5p_jpeg_variant *driver_data = NULL;
2682 const struct of_device_id *match;
2683
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002684 if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
2685 return &s5p_jpeg_drvdata;
2686
2687 match = of_match_node(samsung_jpeg_match, dev->of_node);
2688
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002689 if (match)
2690 driver_data = (struct s5p_jpeg_variant *)match->data;
2691
2692 return driver_data;
2693}
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03002694
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002695static struct platform_driver s5p_jpeg_driver = {
2696 .probe = s5p_jpeg_probe,
2697 .remove = s5p_jpeg_remove,
2698 .driver = {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002699 .of_match_table = of_match_ptr(samsung_jpeg_match),
2700 .owner = THIS_MODULE,
2701 .name = S5P_JPEG_M2M_NAME,
2702 .pm = &s5p_jpeg_pm_ops,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002703 },
2704};
2705
Sachin Kamat87e94292012-07-03 05:54:33 -03002706module_platform_driver(s5p_jpeg_driver);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002707
2708MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002709MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002710MODULE_DESCRIPTION("Samsung JPEG codec driver");
2711MODULE_LICENSE("GPL");