1
2
3
4
5
6
7
8
9
10
11
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>
21#include <linux/of.h>
22#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-v4l2.h>
30#include <media/videobuf2-dma-contig.h>
31
32#include "jpeg-core.h"
33#include "jpeg-hw-s5p.h"
34#include "jpeg-hw-exynos4.h"
35#include "jpeg-hw-exynos3250.h"
36#include "jpeg-regs.h"
37
38static struct s5p_jpeg_fmt sjpeg_formats[] = {
39 {
40 .name = "JPEG JFIF",
41 .fourcc = V4L2_PIX_FMT_JPEG,
42 .flags = SJPEG_FMT_FLAG_ENC_CAPTURE |
43 SJPEG_FMT_FLAG_DEC_OUTPUT |
44 SJPEG_FMT_FLAG_S5P |
45 SJPEG_FMT_FLAG_EXYNOS3250 |
46 SJPEG_FMT_FLAG_EXYNOS4,
47 },
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,
55 .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,
60 },
61 {
62 .name = "YUV 4:2:2 packed, YCbYCr",
63 .fourcc = V4L2_PIX_FMT_YUYV,
64 .depth = 16,
65 .colplanes = 1,
66 .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 {
75 .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 {
88 .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 {
101 .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 {
140 .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,
157 .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,
183 .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 {
204 .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 {
217 .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,
271 .depth = 12,
272 .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,
284 .depth = 12,
285 .colplanes = 2,
286 .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,
299 .h_align = 4,
300 .v_align = 4,
301 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
302 SJPEG_FMT_FLAG_DEC_CAPTURE |
303 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,
312 .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,
325 .h_align = 1,
326 .v_align = 1,
327 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
328 SJPEG_FMT_FLAG_DEC_CAPTURE |
329 SJPEG_FMT_FLAG_EXYNOS3250 |
330 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 {
348 .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 {
361 .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,
370 },
371};
372#define SJPEG_NUM_FORMATS ARRAY_SIZE(sjpeg_formats)
373
374static const unsigned char qtbl_luminance[4][64] = {
375 {
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 {
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
394 },
395 {
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 },
405 {
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
414 }
415};
416
417static const unsigned char qtbl_chrominance[4][64] = {
418 {
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 {
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
437 },
438 {
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 },
448 {
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
457 }
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
494
495
496
497
498
499
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
521
522
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
541 for (i = 0; i < ARRAY_SIZE(fourcc_to_dwngrd_schema_id); ++i) {
542 if (fourcc_to_dwngrd_schema_id[i] == fourcc)
543 return i;
544 }
545
546 return -EINVAL;
547}
548
549static int s5p_jpeg_adjust_fourcc_to_subsampling(
550 enum v4l2_jpeg_chroma_subsampling subs,
551 u32 in_fourcc,
552 u32 *out_fourcc,
553 struct s5p_jpeg_ctx *ctx)
554{
555 int dwngrd_sch_id;
556
557 if (ctx->subsampling != V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
558 dwngrd_sch_id =
559 s5p_jpeg_get_dwngrd_sch_id_by_fourcc(in_fourcc);
560 if (dwngrd_sch_id < 0)
561 return -EINVAL;
562 }
563
564 switch (ctx->subsampling) {
565 case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
566 *out_fourcc = V4L2_PIX_FMT_GREY;
567 break;
568 case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
569 if (dwngrd_sch_id >
570 ARRAY_SIZE(subs420_fourcc_dwngrd_schema) - 1)
571 return -EINVAL;
572 *out_fourcc = subs420_fourcc_dwngrd_schema[dwngrd_sch_id];
573 break;
574 case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
575 if (dwngrd_sch_id >
576 ARRAY_SIZE(subs422_fourcc_dwngrd_schema) - 1)
577 return -EINVAL;
578 *out_fourcc = subs422_fourcc_dwngrd_schema[dwngrd_sch_id];
579 break;
580 default:
581 *out_fourcc = V4L2_PIX_FMT_GREY;
582 break;
583 }
584
585 return 0;
586}
587
588static int exynos4x12_decoded_subsampling[] = {
589 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
590 V4L2_JPEG_CHROMA_SUBSAMPLING_444,
591 V4L2_JPEG_CHROMA_SUBSAMPLING_422,
592 V4L2_JPEG_CHROMA_SUBSAMPLING_420,
593};
594
595static int exynos3250_decoded_subsampling[] = {
596 V4L2_JPEG_CHROMA_SUBSAMPLING_444,
597 V4L2_JPEG_CHROMA_SUBSAMPLING_422,
598 V4L2_JPEG_CHROMA_SUBSAMPLING_420,
599 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
600 -1,
601 -1,
602 V4L2_JPEG_CHROMA_SUBSAMPLING_411,
603};
604
605static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
606{
607 return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
608}
609
610static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh)
611{
612 return container_of(fh, struct s5p_jpeg_ctx, fh);
613}
614
615static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
616{
617 WARN_ON(ctx->subsampling > 3);
618
619 switch (ctx->jpeg->variant->version) {
620 case SJPEG_S5P:
621 if (ctx->subsampling > 2)
622 return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
623 return ctx->subsampling;
624 case SJPEG_EXYNOS3250:
625 case SJPEG_EXYNOS5420:
626 if (ctx->subsampling > 3)
627 return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
628 return exynos3250_decoded_subsampling[ctx->subsampling];
629 case SJPEG_EXYNOS4:
630 case SJPEG_EXYNOS5433:
631 if (ctx->subsampling > 2)
632 return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
633 return exynos4x12_decoded_subsampling[ctx->subsampling];
634 default:
635 return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
636 }
637}
638
639static inline void s5p_jpeg_set_qtbl(void __iomem *regs,
640 const unsigned char *qtbl,
641 unsigned long tab, int len)
642{
643 int i;
644
645 for (i = 0; i < len; i++)
646 writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
647}
648
649static inline void s5p_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
650{
651
652 s5p_jpeg_set_qtbl(regs, qtbl_luminance[quality],
653 S5P_JPG_QTBL_CONTENT(0),
654 ARRAY_SIZE(qtbl_luminance[quality]));
655}
656
657static inline void s5p_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
658{
659
660 s5p_jpeg_set_qtbl(regs, qtbl_chrominance[quality],
661 S5P_JPG_QTBL_CONTENT(1),
662 ARRAY_SIZE(qtbl_chrominance[quality]));
663}
664
665static inline void s5p_jpeg_set_htbl(void __iomem *regs,
666 const unsigned char *htbl,
667 unsigned long tab, int len)
668{
669 int i;
670
671 for (i = 0; i < len; i++)
672 writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
673}
674
675static inline void s5p_jpeg_set_hdctbl(void __iomem *regs)
676{
677
678 s5p_jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0),
679 ARRAY_SIZE(hdctbl0));
680}
681
682static inline void s5p_jpeg_set_hdctblg(void __iomem *regs)
683{
684
685 s5p_jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0),
686 ARRAY_SIZE(hdctblg0));
687}
688
689static inline void s5p_jpeg_set_hactbl(void __iomem *regs)
690{
691
692 s5p_jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0),
693 ARRAY_SIZE(hactbl0));
694}
695
696static inline void s5p_jpeg_set_hactblg(void __iomem *regs)
697{
698
699 s5p_jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0),
700 ARRAY_SIZE(hactblg0));
701}
702
703static inline void exynos4_jpeg_set_tbl(void __iomem *regs,
704 const unsigned char *tbl,
705 unsigned long tab, int len)
706{
707 int i;
708 unsigned int dword;
709
710 for (i = 0; i < len; i += 4) {
711 dword = tbl[i] |
712 (tbl[i + 1] << 8) |
713 (tbl[i + 2] << 16) |
714 (tbl[i + 3] << 24);
715 writel(dword, regs + tab + i);
716 }
717}
718
719static inline void exynos4_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
720{
721
722 exynos4_jpeg_set_tbl(regs, qtbl_luminance[quality],
723 EXYNOS4_QTBL_CONTENT(0),
724 ARRAY_SIZE(qtbl_luminance[quality]));
725}
726
727static inline void exynos4_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
728{
729
730 exynos4_jpeg_set_tbl(regs, qtbl_chrominance[quality],
731 EXYNOS4_QTBL_CONTENT(1),
732 ARRAY_SIZE(qtbl_chrominance[quality]));
733}
734
735static void exynos4_jpeg_set_huff_tbl(void __iomem *base)
736{
737 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCLL,
738 ARRAY_SIZE(hdctbl0));
739 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCCL,
740 ARRAY_SIZE(hdctbl0));
741 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCLV,
742 ARRAY_SIZE(hdctblg0));
743 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCCV,
744 ARRAY_SIZE(hdctblg0));
745 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACLL,
746 ARRAY_SIZE(hactbl0));
747 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACCL,
748 ARRAY_SIZE(hactbl0));
749 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACLV,
750 ARRAY_SIZE(hactblg0));
751 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV,
752 ARRAY_SIZE(hactblg0));
753}
754
755static inline int __exynos4_huff_tbl(int class, int id, bool lenval)
756{
757
758
759
760
761 if (class) {
762 if (id)
763 return lenval ? EXYNOS4_HUFF_TBL_HACCL :
764 EXYNOS4_HUFF_TBL_HACCV;
765 return lenval ? EXYNOS4_HUFF_TBL_HACLL : EXYNOS4_HUFF_TBL_HACLV;
766
767 }
768
769 if (id)
770 return lenval ? EXYNOS4_HUFF_TBL_HDCCL : EXYNOS4_HUFF_TBL_HDCCV;
771
772 return lenval ? EXYNOS4_HUFF_TBL_HDCLL : EXYNOS4_HUFF_TBL_HDCLV;
773}
774
775static inline int exynos4_huff_tbl_len(int class, int id)
776{
777 return __exynos4_huff_tbl(class, id, true);
778}
779
780static inline int exynos4_huff_tbl_val(int class, int id)
781{
782 return __exynos4_huff_tbl(class, id, false);
783}
784
785static int get_byte(struct s5p_jpeg_buffer *buf);
786static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word);
787static void skip(struct s5p_jpeg_buffer *buf, long len);
788
789static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx)
790{
791 struct s5p_jpeg *jpeg = ctx->jpeg;
792 struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
793 struct s5p_jpeg_buffer jpeg_buffer;
794 unsigned int word;
795 int c, x, components;
796
797 jpeg_buffer.size = 2;
798 jpeg_buffer.data =
799 (unsigned long)vb2_plane_vaddr(vb, 0) + ctx->out_q.sos + 2;
800 jpeg_buffer.curr = 0;
801
802 word = 0;
803
804 if (get_word_be(&jpeg_buffer, &word))
805 return;
806 jpeg_buffer.size = (long)word - 2;
807 jpeg_buffer.data += 2;
808 jpeg_buffer.curr = 0;
809
810 components = get_byte(&jpeg_buffer);
811 if (components == -1)
812 return;
813 while (components--) {
814 c = get_byte(&jpeg_buffer);
815 if (c == -1)
816 return;
817 x = get_byte(&jpeg_buffer);
818 if (x == -1)
819 return;
820 exynos4_jpeg_select_dec_h_tbl(jpeg->regs, c,
821 (((x >> 4) & 0x1) << 1) | (x & 0x1));
822 }
823
824}
825
826static void exynos4_jpeg_parse_huff_tbl(struct s5p_jpeg_ctx *ctx)
827{
828 struct s5p_jpeg *jpeg = ctx->jpeg;
829 struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
830 struct s5p_jpeg_buffer jpeg_buffer;
831 unsigned int word;
832 int c, i, n, j;
833
834 for (j = 0; j < ctx->out_q.dht.n; ++j) {
835 jpeg_buffer.size = ctx->out_q.dht.len[j];
836 jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(vb, 0) +
837 ctx->out_q.dht.marker[j];
838 jpeg_buffer.curr = 0;
839
840 word = 0;
841 while (jpeg_buffer.curr < jpeg_buffer.size) {
842 char id, class;
843
844 c = get_byte(&jpeg_buffer);
845 if (c == -1)
846 return;
847 id = c & 0xf;
848 class = (c >> 4) & 0xf;
849 n = 0;
850 for (i = 0; i < 16; ++i) {
851 c = get_byte(&jpeg_buffer);
852 if (c == -1)
853 return;
854 word |= c << ((i % 4) * 8);
855 if ((i + 1) % 4 == 0) {
856 writel(word, jpeg->regs +
857 exynos4_huff_tbl_len(class, id) +
858 (i / 4) * 4);
859 word = 0;
860 }
861 n += c;
862 }
863 word = 0;
864 for (i = 0; i < n; ++i) {
865 c = get_byte(&jpeg_buffer);
866 if (c == -1)
867 return;
868 word |= c << ((i % 4) * 8);
869 if ((i + 1) % 4 == 0) {
870 writel(word, jpeg->regs +
871 exynos4_huff_tbl_val(class, id) +
872 (i / 4) * 4);
873 word = 0;
874 }
875 }
876 if (i % 4) {
877 writel(word, jpeg->regs +
878 exynos4_huff_tbl_val(class, id) + (i / 4) * 4);
879 }
880 word = 0;
881 }
882 }
883}
884
885static void exynos4_jpeg_parse_decode_q_tbl(struct s5p_jpeg_ctx *ctx)
886{
887 struct s5p_jpeg *jpeg = ctx->jpeg;
888 struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
889 struct s5p_jpeg_buffer jpeg_buffer;
890 int c, x, components;
891
892 jpeg_buffer.size = ctx->out_q.sof_len;
893 jpeg_buffer.data =
894 (unsigned long)vb2_plane_vaddr(vb, 0) + ctx->out_q.sof;
895 jpeg_buffer.curr = 0;
896
897 skip(&jpeg_buffer, 5);
898 components = get_byte(&jpeg_buffer);
899 if (components == -1)
900 return;
901
902 exynos4_jpeg_set_dec_components(jpeg->regs, components);
903
904 while (components--) {
905 c = get_byte(&jpeg_buffer);
906 if (c == -1)
907 return;
908 skip(&jpeg_buffer, 1);
909 x = get_byte(&jpeg_buffer);
910 if (x == -1)
911 return;
912 exynos4_jpeg_select_dec_q_tbl(jpeg->regs, c, x);
913 }
914}
915
916static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx)
917{
918 struct s5p_jpeg *jpeg = ctx->jpeg;
919 struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
920 struct s5p_jpeg_buffer jpeg_buffer;
921 unsigned int word;
922 int c, i, j;
923
924 for (j = 0; j < ctx->out_q.dqt.n; ++j) {
925 jpeg_buffer.size = ctx->out_q.dqt.len[j];
926 jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(vb, 0) +
927 ctx->out_q.dqt.marker[j];
928 jpeg_buffer.curr = 0;
929
930 word = 0;
931 while (jpeg_buffer.size - jpeg_buffer.curr >= 65) {
932 char id;
933
934 c = get_byte(&jpeg_buffer);
935 if (c == -1)
936 return;
937 id = c & 0xf;
938
939 if ((c >> 4) & 0xf)
940 return;
941 for (i = 0; i < 64; ++i) {
942 c = get_byte(&jpeg_buffer);
943 if (c == -1)
944 return;
945 word |= c << ((i % 4) * 8);
946 if ((i + 1) % 4 == 0) {
947 writel(word, jpeg->regs +
948 EXYNOS4_QTBL_CONTENT(id) + (i / 4) * 4);
949 word = 0;
950 }
951 }
952 word = 0;
953 }
954 }
955}
956
957
958
959
960
961
962
963static int queue_init(void *priv, struct vb2_queue *src_vq,
964 struct vb2_queue *dst_vq);
965static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
966 __u32 pixelformat, unsigned int fmt_type);
967static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx);
968
969static int s5p_jpeg_open(struct file *file)
970{
971 struct s5p_jpeg *jpeg = video_drvdata(file);
972 struct video_device *vfd = video_devdata(file);
973 struct s5p_jpeg_ctx *ctx;
974 struct s5p_jpeg_fmt *out_fmt, *cap_fmt;
975 int ret = 0;
976
977 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
978 if (!ctx)
979 return -ENOMEM;
980
981 if (mutex_lock_interruptible(&jpeg->lock)) {
982 ret = -ERESTARTSYS;
983 goto free;
984 }
985
986 v4l2_fh_init(&ctx->fh, vfd);
987
988 ctx->fh.ctrl_handler = &ctx->ctrl_handler;
989 file->private_data = &ctx->fh;
990 v4l2_fh_add(&ctx->fh);
991
992 ctx->jpeg = jpeg;
993 if (vfd == jpeg->vfd_encoder) {
994 ctx->mode = S5P_JPEG_ENCODE;
995 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_RGB565,
996 FMT_TYPE_OUTPUT);
997 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
998 FMT_TYPE_CAPTURE);
999 } else {
1000 ctx->mode = S5P_JPEG_DECODE;
1001 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
1002 FMT_TYPE_OUTPUT);
1003 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
1004 FMT_TYPE_CAPTURE);
1005 ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
1006 }
1007
1008 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
1009 if (IS_ERR(ctx->fh.m2m_ctx)) {
1010 ret = PTR_ERR(ctx->fh.m2m_ctx);
1011 goto error;
1012 }
1013
1014 ctx->out_q.fmt = out_fmt;
1015 ctx->cap_q.fmt = cap_fmt;
1016
1017 ret = s5p_jpeg_controls_create(ctx);
1018 if (ret < 0)
1019 goto error;
1020
1021 mutex_unlock(&jpeg->lock);
1022 return 0;
1023
1024error:
1025 v4l2_fh_del(&ctx->fh);
1026 v4l2_fh_exit(&ctx->fh);
1027 mutex_unlock(&jpeg->lock);
1028free:
1029 kfree(ctx);
1030 return ret;
1031}
1032
1033static int s5p_jpeg_release(struct file *file)
1034{
1035 struct s5p_jpeg *jpeg = video_drvdata(file);
1036 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
1037
1038 mutex_lock(&jpeg->lock);
1039 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
1040 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1041 v4l2_fh_del(&ctx->fh);
1042 v4l2_fh_exit(&ctx->fh);
1043 kfree(ctx);
1044 mutex_unlock(&jpeg->lock);
1045
1046 return 0;
1047}
1048
1049static const struct v4l2_file_operations s5p_jpeg_fops = {
1050 .owner = THIS_MODULE,
1051 .open = s5p_jpeg_open,
1052 .release = s5p_jpeg_release,
1053 .poll = v4l2_m2m_fop_poll,
1054 .unlocked_ioctl = video_ioctl2,
1055 .mmap = v4l2_m2m_fop_mmap,
1056};
1057
1058
1059
1060
1061
1062
1063
1064static int get_byte(struct s5p_jpeg_buffer *buf)
1065{
1066 if (buf->curr >= buf->size)
1067 return -1;
1068
1069 return ((unsigned char *)buf->data)[buf->curr++];
1070}
1071
1072static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
1073{
1074 unsigned int temp;
1075 int byte;
1076
1077 byte = get_byte(buf);
1078 if (byte == -1)
1079 return -1;
1080 temp = byte << 8;
1081 byte = get_byte(buf);
1082 if (byte == -1)
1083 return -1;
1084 *word = (unsigned int)byte | temp;
1085 return 0;
1086}
1087
1088static void skip(struct s5p_jpeg_buffer *buf, long len)
1089{
1090 if (len <= 0)
1091 return;
1092
1093 while (len--)
1094 get_byte(buf);
1095}
1096
1097static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
1098 unsigned long buffer, unsigned long size,
1099 struct s5p_jpeg_ctx *ctx)
1100{
1101 int c, components = 0, notfound, n_dht = 0, n_dqt = 0;
1102 unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0,
1103 sof_len = 0;
1104 unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER],
1105 dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
1106 long length;
1107 struct s5p_jpeg_buffer jpeg_buffer;
1108
1109 jpeg_buffer.size = size;
1110 jpeg_buffer.data = buffer;
1111 jpeg_buffer.curr = 0;
1112
1113 notfound = 1;
1114 while (notfound || !sos) {
1115 c = get_byte(&jpeg_buffer);
1116 if (c == -1)
1117 return false;
1118 if (c != 0xff)
1119 continue;
1120 do
1121 c = get_byte(&jpeg_buffer);
1122 while (c == 0xff);
1123 if (c == -1)
1124 return false;
1125 if (c == 0)
1126 continue;
1127 length = 0;
1128 switch (c) {
1129
1130 case SOF0:
1131 if (get_word_be(&jpeg_buffer, &word))
1132 break;
1133 length = (long)word - 2;
1134 if (!length)
1135 return false;
1136 sof = jpeg_buffer.curr;
1137 sof_len = length;
1138 if (get_byte(&jpeg_buffer) == -1)
1139 break;
1140 if (get_word_be(&jpeg_buffer, &height))
1141 break;
1142 if (get_word_be(&jpeg_buffer, &width))
1143 break;
1144 components = get_byte(&jpeg_buffer);
1145 if (components == -1)
1146 break;
1147
1148 if (components == 1) {
1149 subsampling = 0x33;
1150 } else {
1151 skip(&jpeg_buffer, 1);
1152 subsampling = get_byte(&jpeg_buffer);
1153 skip(&jpeg_buffer, 1);
1154 }
1155 if (components > 3)
1156 return false;
1157 skip(&jpeg_buffer, components * 2);
1158 notfound = 0;
1159 break;
1160
1161 case DQT:
1162 if (get_word_be(&jpeg_buffer, &word))
1163 break;
1164 length = (long)word - 2;
1165 if (!length)
1166 return false;
1167 if (n_dqt >= S5P_JPEG_MAX_MARKER)
1168 return false;
1169 dqt[n_dqt] = jpeg_buffer.curr;
1170 dqt_len[n_dqt++] = length;
1171 skip(&jpeg_buffer, length);
1172 break;
1173
1174 case DHT:
1175 if (get_word_be(&jpeg_buffer, &word))
1176 break;
1177 length = (long)word - 2;
1178 if (!length)
1179 return false;
1180 if (n_dht >= S5P_JPEG_MAX_MARKER)
1181 return false;
1182 dht[n_dht] = jpeg_buffer.curr;
1183 dht_len[n_dht++] = length;
1184 skip(&jpeg_buffer, length);
1185 break;
1186
1187 case SOS:
1188 sos = jpeg_buffer.curr - 2;
1189 break;
1190
1191
1192 case RST ... RST + 7:
1193 case SOI:
1194 case EOI:
1195 case TEM:
1196 break;
1197
1198
1199 default:
1200 if (get_word_be(&jpeg_buffer, &word))
1201 break;
1202 length = (long)word - 2;
1203 skip(&jpeg_buffer, length);
1204 break;
1205 }
1206 }
1207 result->w = width;
1208 result->h = height;
1209 result->sos = sos;
1210 result->dht.n = n_dht;
1211 while (n_dht--) {
1212 result->dht.marker[n_dht] = dht[n_dht];
1213 result->dht.len[n_dht] = dht_len[n_dht];
1214 }
1215 result->dqt.n = n_dqt;
1216 while (n_dqt--) {
1217 result->dqt.marker[n_dqt] = dqt[n_dqt];
1218 result->dqt.len[n_dqt] = dqt_len[n_dqt];
1219 }
1220 result->sof = sof;
1221 result->sof_len = sof_len;
1222 result->size = result->components = components;
1223
1224 switch (subsampling) {
1225 case 0x11:
1226 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444;
1227 break;
1228 case 0x21:
1229 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422;
1230 break;
1231 case 0x22:
1232 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420;
1233 break;
1234 case 0x33:
1235 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
1236 break;
1237 default:
1238 return false;
1239 }
1240
1241 return !notfound && sos;
1242}
1243
1244static int s5p_jpeg_querycap(struct file *file, void *priv,
1245 struct v4l2_capability *cap)
1246{
1247 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
1248
1249 if (ctx->mode == S5P_JPEG_ENCODE) {
1250 strlcpy(cap->driver, S5P_JPEG_M2M_NAME,
1251 sizeof(cap->driver));
1252 strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
1253 sizeof(cap->card));
1254 } else {
1255 strlcpy(cap->driver, S5P_JPEG_M2M_NAME,
1256 sizeof(cap->driver));
1257 strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
1258 sizeof(cap->card));
1259 }
1260 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
1261 dev_name(ctx->jpeg->dev));
1262 cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
1263 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1264 return 0;
1265}
1266
1267static int enum_fmt(struct s5p_jpeg_fmt *sjpeg_formats, int n,
1268 struct v4l2_fmtdesc *f, u32 type)
1269{
1270 int i, num = 0;
1271
1272 for (i = 0; i < n; ++i) {
1273 if (sjpeg_formats[i].flags & type) {
1274
1275 if (num == f->index)
1276 break;
1277
1278
1279
1280 ++num;
1281 }
1282 }
1283
1284
1285 if (i >= n)
1286 return -EINVAL;
1287
1288 strlcpy(f->description, sjpeg_formats[i].name, sizeof(f->description));
1289 f->pixelformat = sjpeg_formats[i].fourcc;
1290
1291 return 0;
1292}
1293
1294static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
1295 struct v4l2_fmtdesc *f)
1296{
1297 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
1298
1299 if (ctx->mode == S5P_JPEG_ENCODE)
1300 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
1301 SJPEG_FMT_FLAG_ENC_CAPTURE);
1302
1303 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
1304 SJPEG_FMT_FLAG_DEC_CAPTURE);
1305}
1306
1307static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
1308 struct v4l2_fmtdesc *f)
1309{
1310 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
1311
1312 if (ctx->mode == S5P_JPEG_ENCODE)
1313 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
1314 SJPEG_FMT_FLAG_ENC_OUTPUT);
1315
1316 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
1317 SJPEG_FMT_FLAG_DEC_OUTPUT);
1318}
1319
1320static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
1321 enum v4l2_buf_type type)
1322{
1323 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1324 return &ctx->out_q;
1325 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1326 return &ctx->cap_q;
1327
1328 return NULL;
1329}
1330
1331static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
1332{
1333 struct vb2_queue *vq;
1334 struct s5p_jpeg_q_data *q_data = NULL;
1335 struct v4l2_pix_format *pix = &f->fmt.pix;
1336 struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);
1337
1338 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
1339 if (!vq)
1340 return -EINVAL;
1341
1342 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1343 ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
1344 return -EINVAL;
1345 q_data = get_q_data(ct, f->type);
1346 BUG_ON(q_data == NULL);
1347
1348 pix->width = q_data->w;
1349 pix->height = q_data->h;
1350 pix->field = V4L2_FIELD_NONE;
1351 pix->pixelformat = q_data->fmt->fourcc;
1352 pix->bytesperline = 0;
1353 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
1354 u32 bpl = q_data->w;
1355
1356 if (q_data->fmt->colplanes == 1)
1357 bpl = (bpl * q_data->fmt->depth) >> 3;
1358 pix->bytesperline = bpl;
1359 }
1360 pix->sizeimage = q_data->size;
1361
1362 return 0;
1363}
1364
1365static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
1366 u32 pixelformat, unsigned int fmt_type)
1367{
1368 unsigned int k, fmt_flag;
1369
1370 if (ctx->mode == S5P_JPEG_ENCODE)
1371 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
1372 SJPEG_FMT_FLAG_ENC_OUTPUT :
1373 SJPEG_FMT_FLAG_ENC_CAPTURE;
1374 else
1375 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
1376 SJPEG_FMT_FLAG_DEC_OUTPUT :
1377 SJPEG_FMT_FLAG_DEC_CAPTURE;
1378
1379 for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) {
1380 struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k];
1381
1382 if (fmt->fourcc == pixelformat &&
1383 fmt->flags & fmt_flag &&
1384 fmt->flags & ctx->jpeg->variant->fmt_ver_flag) {
1385 return fmt;
1386 }
1387 }
1388
1389 return NULL;
1390}
1391
1392static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
1393 u32 *w, unsigned int wmin, unsigned int wmax,
1394 unsigned int walign,
1395 u32 *h, unsigned int hmin, unsigned int hmax,
1396 unsigned int halign)
1397{
1398 int width, height, w_step, h_step;
1399
1400 width = *w;
1401 height = *h;
1402
1403 w_step = 1 << walign;
1404 h_step = 1 << halign;
1405
1406 if (ctx->jpeg->variant->hw3250_compat) {
1407
1408
1409
1410
1411
1412
1413
1414 if (w_step == 4 && ((width & 3) == 1)) {
1415 wmax = width;
1416 hmax = height;
1417 }
1418 }
1419
1420 v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
1421
1422 if (*w < width && (*w + w_step) < wmax)
1423 *w += w_step;
1424 if (*h < height && (*h + h_step) < hmax)
1425 *h += h_step;
1426}
1427
1428static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
1429 struct s5p_jpeg_ctx *ctx, int q_type)
1430{
1431 struct v4l2_pix_format *pix = &f->fmt.pix;
1432
1433 if (pix->field == V4L2_FIELD_ANY)
1434 pix->field = V4L2_FIELD_NONE;
1435 else if (pix->field != V4L2_FIELD_NONE)
1436 return -EINVAL;
1437
1438
1439
1440
1441 if (q_type == FMT_TYPE_OUTPUT)
1442 jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
1443 S5P_JPEG_MAX_WIDTH, 0,
1444 &pix->height, S5P_JPEG_MIN_HEIGHT,
1445 S5P_JPEG_MAX_HEIGHT, 0);
1446 else
1447 jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
1448 S5P_JPEG_MAX_WIDTH, fmt->h_align,
1449 &pix->height, S5P_JPEG_MIN_HEIGHT,
1450 S5P_JPEG_MAX_HEIGHT, fmt->v_align);
1451
1452 if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
1453 if (pix->sizeimage <= 0)
1454 pix->sizeimage = PAGE_SIZE;
1455 pix->bytesperline = 0;
1456 } else {
1457 u32 bpl = pix->bytesperline;
1458
1459 if (fmt->colplanes > 1 && bpl < pix->width)
1460 bpl = pix->width;
1461
1462 if (fmt->colplanes == 1 &&
1463 (bpl << 3) / fmt->depth < pix->width)
1464 bpl = (pix->width * fmt->depth) >> 3;
1465
1466 pix->bytesperline = bpl;
1467 pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
1468 }
1469
1470 return 0;
1471}
1472
1473static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
1474 struct v4l2_format *f)
1475{
1476 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
1477 struct v4l2_pix_format *pix = &f->fmt.pix;
1478 struct s5p_jpeg_fmt *fmt;
1479 int ret;
1480
1481 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1482 FMT_TYPE_CAPTURE);
1483 if (!fmt) {
1484 v4l2_err(&ctx->jpeg->v4l2_dev,
1485 "Fourcc format (0x%08x) invalid.\n",
1486 f->fmt.pix.pixelformat);
1487 return -EINVAL;
1488 }
1489
1490 if (!ctx->jpeg->variant->hw_ex4_compat || ctx->mode != S5P_JPEG_DECODE)
1491 goto exit;
1492
1493
1494
1495
1496
1497
1498
1499 if ((fmt->flags & SJPEG_FMT_NON_RGB) &&
1500 (fmt->subsampling < ctx->subsampling)) {
1501 ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
1502 fmt->fourcc,
1503 &pix->pixelformat,
1504 ctx);
1505 if (ret < 0)
1506 pix->pixelformat = V4L2_PIX_FMT_GREY;
1507
1508 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1509 FMT_TYPE_CAPTURE);
1510 }
1511
1512
1513
1514
1515
1516
1517
1518 if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
1519 (ctx->out_q.w & 1) &&
1520 (pix->pixelformat == V4L2_PIX_FMT_NV12 ||
1521 pix->pixelformat == V4L2_PIX_FMT_NV21 ||
1522 pix->pixelformat == V4L2_PIX_FMT_YUV420)) {
1523 pix->pixelformat = V4L2_PIX_FMT_RGB565;
1524 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1525 FMT_TYPE_CAPTURE);
1526 }
1527
1528exit:
1529 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
1530}
1531
1532static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
1533 struct v4l2_format *f)
1534{
1535 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
1536 struct s5p_jpeg_fmt *fmt;
1537
1538 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1539 FMT_TYPE_OUTPUT);
1540 if (!fmt) {
1541 v4l2_err(&ctx->jpeg->v4l2_dev,
1542 "Fourcc format (0x%08x) invalid.\n",
1543 f->fmt.pix.pixelformat);
1544 return -EINVAL;
1545 }
1546
1547 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);
1548}
1549
1550static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
1551 struct v4l2_format *f,
1552 int fmt_depth)
1553{
1554 struct v4l2_pix_format *pix = &f->fmt.pix;
1555 u32 pix_fmt = f->fmt.pix.pixelformat;
1556 int w = pix->width, h = pix->height, wh_align;
1557 int padding = 0;
1558
1559 if (pix_fmt == V4L2_PIX_FMT_RGB32 ||
1560 pix_fmt == V4L2_PIX_FMT_RGB565 ||
1561 pix_fmt == V4L2_PIX_FMT_NV24 ||
1562 pix_fmt == V4L2_PIX_FMT_NV42 ||
1563 pix_fmt == V4L2_PIX_FMT_NV12 ||
1564 pix_fmt == V4L2_PIX_FMT_NV21 ||
1565 pix_fmt == V4L2_PIX_FMT_YUV420)
1566 wh_align = 4;
1567 else
1568 wh_align = 1;
1569
1570 jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH,
1571 S5P_JPEG_MAX_WIDTH, wh_align,
1572 &h, S5P_JPEG_MIN_HEIGHT,
1573 S5P_JPEG_MAX_HEIGHT, wh_align);
1574
1575 if (ctx->jpeg->variant->version == SJPEG_EXYNOS4)
1576 padding = PAGE_SIZE;
1577
1578 return (w * h * fmt_depth >> 3) + padding;
1579}
1580
1581static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
1582 struct v4l2_rect *r);
1583
1584static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
1585{
1586 struct vb2_queue *vq;
1587 struct s5p_jpeg_q_data *q_data = NULL;
1588 struct v4l2_pix_format *pix = &f->fmt.pix;
1589 struct v4l2_ctrl *ctrl_subs;
1590 struct v4l2_rect scale_rect;
1591 unsigned int f_type;
1592
1593 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
1594 if (!vq)
1595 return -EINVAL;
1596
1597 q_data = get_q_data(ct, f->type);
1598 BUG_ON(q_data == NULL);
1599
1600 if (vb2_is_busy(vq)) {
1601 v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
1602 return -EBUSY;
1603 }
1604
1605 f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
1606 FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;
1607
1608 q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);
1609 q_data->w = pix->width;
1610 q_data->h = pix->height;
1611 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
1612
1613
1614
1615
1616
1617
1618 if (ct->jpeg->variant->hw_ex4_compat &&
1619 f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)
1620 q_data->size = exynos4_jpeg_get_output_buffer_size(ct,
1621 f,
1622 q_data->fmt->depth);
1623 else
1624 q_data->size = q_data->w * q_data->h *
1625 q_data->fmt->depth >> 3;
1626 } else {
1627 q_data->size = pix->sizeimage;
1628 }
1629
1630 if (f_type == FMT_TYPE_OUTPUT) {
1631 ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler,
1632 V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
1633 if (ctrl_subs)
1634 v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
1635 ct->crop_altered = false;
1636 }
1637
1638
1639
1640
1641
1642
1643
1644 if (!ct->crop_altered &&
1645 ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) ||
1646 (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) {
1647 ct->crop_rect.width = pix->width;
1648 ct->crop_rect.height = pix->height;
1649 }
1650
1651
1652
1653
1654
1655
1656 if (ct->mode == S5P_JPEG_DECODE &&
1657 f_type == FMT_TYPE_CAPTURE &&
1658 ct->jpeg->variant->hw3250_compat &&
1659 pix->pixelformat == V4L2_PIX_FMT_YUV420 &&
1660 ct->scale_factor > 2) {
1661 scale_rect.width = ct->out_q.w / 2;
1662 scale_rect.height = ct->out_q.h / 2;
1663 exynos3250_jpeg_try_downscale(ct, &scale_rect);
1664 }
1665
1666 return 0;
1667}
1668
1669static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
1670 struct v4l2_format *f)
1671{
1672 int ret;
1673
1674 ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
1675 if (ret)
1676 return ret;
1677
1678 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
1679}
1680
1681static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
1682 struct v4l2_format *f)
1683{
1684 int ret;
1685
1686 ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
1687 if (ret)
1688 return ret;
1689
1690 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
1691}
1692
1693static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
1694 struct v4l2_rect *r)
1695{
1696 int w_ratio, h_ratio, scale_factor, cur_ratio, i;
1697
1698 w_ratio = ctx->out_q.w / r->width;
1699 h_ratio = ctx->out_q.h / r->height;
1700
1701 scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio;
1702 scale_factor = clamp_val(scale_factor, 1, 8);
1703
1704
1705 for (i = 0; i <= 3; ++i) {
1706 cur_ratio = 1 << i;
1707 if (scale_factor <= cur_ratio) {
1708 ctx->scale_factor = cur_ratio;
1709 break;
1710 }
1711 }
1712
1713 r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);
1714 r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);
1715
1716 ctx->crop_rect.width = r->width;
1717 ctx->crop_rect.height = r->height;
1718 ctx->crop_rect.left = 0;
1719 ctx->crop_rect.top = 0;
1720
1721 ctx->crop_altered = true;
1722
1723 return 0;
1724}
1725
1726
1727static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
1728{
1729 if (a->left < b->left || a->top < b->top)
1730 return 0;
1731 if (a->left + a->width > b->left + b->width)
1732 return 0;
1733 if (a->top + a->height > b->top + b->height)
1734 return 0;
1735
1736 return 1;
1737}
1738
1739static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,
1740 struct v4l2_rect *r)
1741{
1742 struct v4l2_rect base_rect;
1743 int w_step, h_step;
1744
1745 switch (ctx->cap_q.fmt->fourcc) {
1746 case V4L2_PIX_FMT_NV12:
1747 case V4L2_PIX_FMT_NV21:
1748 w_step = 1;
1749 h_step = 2;
1750 break;
1751 case V4L2_PIX_FMT_YUV420:
1752 w_step = 2;
1753 h_step = 2;
1754 break;
1755 default:
1756 w_step = 1;
1757 h_step = 1;
1758 break;
1759 }
1760
1761 base_rect.top = 0;
1762 base_rect.left = 0;
1763 base_rect.width = ctx->out_q.w;
1764 base_rect.height = ctx->out_q.h;
1765
1766 r->width = round_down(r->width, w_step);
1767 r->height = round_down(r->height, h_step);
1768 r->left = round_down(r->left, 2);
1769 r->top = round_down(r->top, 2);
1770
1771 if (!enclosed_rectangle(r, &base_rect))
1772 return -EINVAL;
1773
1774 ctx->crop_rect.left = r->left;
1775 ctx->crop_rect.top = r->top;
1776 ctx->crop_rect.width = r->width;
1777 ctx->crop_rect.height = r->height;
1778
1779 ctx->crop_altered = true;
1780
1781 return 0;
1782}
1783
1784
1785
1786
1787
1788static int s5p_jpeg_g_selection(struct file *file, void *priv,
1789 struct v4l2_selection *s)
1790{
1791 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
1792
1793 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
1794 s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1795 return -EINVAL;
1796
1797
1798 switch (s->target) {
1799 case V4L2_SEL_TGT_CROP:
1800 case V4L2_SEL_TGT_CROP_BOUNDS:
1801 case V4L2_SEL_TGT_CROP_DEFAULT:
1802 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1803 s->r.width = ctx->out_q.w;
1804 s->r.height = ctx->out_q.h;
1805 s->r.left = 0;
1806 s->r.top = 0;
1807 break;
1808 case V4L2_SEL_TGT_COMPOSE:
1809 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1810 case V4L2_SEL_TGT_COMPOSE_PADDED:
1811 s->r.width = ctx->crop_rect.width;
1812 s->r.height = ctx->crop_rect.height;
1813 s->r.left = ctx->crop_rect.left;
1814 s->r.top = ctx->crop_rect.top;
1815 break;
1816 default:
1817 return -EINVAL;
1818 }
1819 return 0;
1820}
1821
1822
1823
1824
1825static int s5p_jpeg_s_selection(struct file *file, void *fh,
1826 struct v4l2_selection *s)
1827{
1828 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
1829 struct v4l2_rect *rect = &s->r;
1830 int ret = -EINVAL;
1831
1832 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1833 return -EINVAL;
1834
1835 if (s->target == V4L2_SEL_TGT_COMPOSE) {
1836 if (ctx->mode != S5P_JPEG_DECODE)
1837 return -EINVAL;
1838 if (ctx->jpeg->variant->hw3250_compat)
1839 ret = exynos3250_jpeg_try_downscale(ctx, rect);
1840 } else if (s->target == V4L2_SEL_TGT_CROP) {
1841 if (ctx->mode != S5P_JPEG_ENCODE)
1842 return -EINVAL;
1843 if (ctx->jpeg->variant->hw3250_compat)
1844 ret = exynos3250_jpeg_try_crop(ctx, rect);
1845 }
1846
1847 return ret;
1848}
1849
1850static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1851{
1852 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1853 struct s5p_jpeg *jpeg = ctx->jpeg;
1854 unsigned long flags;
1855
1856 switch (ctrl->id) {
1857 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1858 spin_lock_irqsave(&jpeg->slock, flags);
1859 ctrl->val = s5p_jpeg_to_user_subsampling(ctx);
1860 spin_unlock_irqrestore(&jpeg->slock, flags);
1861 break;
1862 }
1863
1864 return 0;
1865}
1866
1867static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
1868{
1869 switch (ctx->jpeg->variant->version) {
1870 case SJPEG_S5P:
1871 return 0;
1872 case SJPEG_EXYNOS3250:
1873 case SJPEG_EXYNOS5420:
1874
1875
1876
1877
1878 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
1879 *ctrl_val = 0;
1880 break;
1881 case SJPEG_EXYNOS4:
1882
1883
1884
1885
1886
1887 if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
1888 *ctrl_val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY)
1889 return -EINVAL;
1890 break;
1891 }
1892
1893
1894
1895
1896
1897
1898 if (ctx->out_q.fmt->subsampling > *ctrl_val)
1899 *ctrl_val = ctx->out_q.fmt->subsampling;
1900
1901 return 0;
1902}
1903
1904static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
1905{
1906 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1907 unsigned long flags;
1908 int ret = 0;
1909
1910 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1911
1912 if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING)
1913 ret = s5p_jpeg_adjust_subs_ctrl(ctx, &ctrl->val);
1914
1915 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1916 return ret;
1917}
1918
1919static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
1920{
1921 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1922 unsigned long flags;
1923
1924 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1925
1926 switch (ctrl->id) {
1927 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
1928 ctx->compr_quality = ctrl->val;
1929 break;
1930 case V4L2_CID_JPEG_RESTART_INTERVAL:
1931 ctx->restart_interval = ctrl->val;
1932 break;
1933 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1934 ctx->subsampling = ctrl->val;
1935 break;
1936 }
1937
1938 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1939 return 0;
1940}
1941
1942static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {
1943 .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl,
1944 .try_ctrl = s5p_jpeg_try_ctrl,
1945 .s_ctrl = s5p_jpeg_s_ctrl,
1946};
1947
1948static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)
1949{
1950 unsigned int mask = ~0x27;
1951 struct v4l2_ctrl *ctrl;
1952 int ret;
1953
1954 v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
1955
1956 if (ctx->mode == S5P_JPEG_ENCODE) {
1957 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1958 V4L2_CID_JPEG_COMPRESSION_QUALITY,
1959 0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);
1960
1961 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1962 V4L2_CID_JPEG_RESTART_INTERVAL,
1963 0, 3, 0xffff, 0);
1964 if (ctx->jpeg->variant->version == SJPEG_S5P)
1965 mask = ~0x06;
1966 }
1967
1968 ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1969 V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
1970 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,
1971 V4L2_JPEG_CHROMA_SUBSAMPLING_422);
1972
1973 if (ctx->ctrl_handler.error) {
1974 ret = ctx->ctrl_handler.error;
1975 goto error_free;
1976 }
1977
1978 if (ctx->mode == S5P_JPEG_DECODE)
1979 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |
1980 V4L2_CTRL_FLAG_READ_ONLY;
1981
1982 ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
1983 if (ret < 0)
1984 goto error_free;
1985
1986 return ret;
1987
1988error_free:
1989 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1990 return ret;
1991}
1992
1993static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
1994 .vidioc_querycap = s5p_jpeg_querycap,
1995
1996 .vidioc_enum_fmt_vid_cap = s5p_jpeg_enum_fmt_vid_cap,
1997 .vidioc_enum_fmt_vid_out = s5p_jpeg_enum_fmt_vid_out,
1998
1999 .vidioc_g_fmt_vid_cap = s5p_jpeg_g_fmt,
2000 .vidioc_g_fmt_vid_out = s5p_jpeg_g_fmt,
2001
2002 .vidioc_try_fmt_vid_cap = s5p_jpeg_try_fmt_vid_cap,
2003 .vidioc_try_fmt_vid_out = s5p_jpeg_try_fmt_vid_out,
2004
2005 .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap,
2006 .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out,
2007
2008 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
2009 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
2010 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
2011 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
2012
2013 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
2014 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
2015
2016 .vidioc_g_selection = s5p_jpeg_g_selection,
2017 .vidioc_s_selection = s5p_jpeg_s_selection,
2018};
2019
2020
2021
2022
2023
2024
2025
2026static void s5p_jpeg_device_run(void *priv)
2027{
2028 struct s5p_jpeg_ctx *ctx = priv;
2029 struct s5p_jpeg *jpeg = ctx->jpeg;
2030 struct vb2_buffer *src_buf, *dst_buf;
2031 unsigned long src_addr, dst_addr, flags;
2032
2033 spin_lock_irqsave(&ctx->jpeg->slock, flags);
2034
2035 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2036 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2037 src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
2038 dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
2039
2040 s5p_jpeg_reset(jpeg->regs);
2041 s5p_jpeg_poweron(jpeg->regs);
2042 s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);
2043 if (ctx->mode == S5P_JPEG_ENCODE) {
2044 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
2045 s5p_jpeg_input_raw_mode(jpeg->regs,
2046 S5P_JPEG_RAW_IN_565);
2047 else
2048 s5p_jpeg_input_raw_mode(jpeg->regs,
2049 S5P_JPEG_RAW_IN_422);
2050 s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
2051 s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);
2052 s5p_jpeg_x(jpeg->regs, ctx->out_q.w);
2053 s5p_jpeg_y(jpeg->regs, ctx->out_q.h);
2054 s5p_jpeg_imgadr(jpeg->regs, src_addr);
2055 s5p_jpeg_jpgadr(jpeg->regs, dst_addr);
2056
2057
2058 s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
2059
2060
2061 s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
2062 s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
2063 s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
2064 s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
2065 s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
2066 s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
2067 s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
2068 s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
2069 s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
2070
2071
2072
2073
2074
2075 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
2076 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
2077
2078 s5p_jpeg_qtbl(jpeg->regs, 1, 0);
2079
2080 s5p_jpeg_qtbl(jpeg->regs, 2, 1);
2081 s5p_jpeg_qtbl(jpeg->regs, 3, 1);
2082
2083
2084 s5p_jpeg_htbl_ac(jpeg->regs, 1);
2085 s5p_jpeg_htbl_dc(jpeg->regs, 1);
2086 s5p_jpeg_htbl_ac(jpeg->regs, 2);
2087 s5p_jpeg_htbl_dc(jpeg->regs, 2);
2088 s5p_jpeg_htbl_ac(jpeg->regs, 3);
2089 s5p_jpeg_htbl_dc(jpeg->regs, 3);
2090 } else {
2091 s5p_jpeg_rst_int_enable(jpeg->regs, true);
2092 s5p_jpeg_data_num_int_enable(jpeg->regs, true);
2093 s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);
2094 if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
2095 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
2096 else
2097 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
2098 s5p_jpeg_jpgadr(jpeg->regs, src_addr);
2099 s5p_jpeg_imgadr(jpeg->regs, dst_addr);
2100 }
2101
2102 s5p_jpeg_start(jpeg->regs);
2103
2104 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
2105}
2106
2107static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
2108{
2109 struct s5p_jpeg *jpeg = ctx->jpeg;
2110 struct s5p_jpeg_fmt *fmt;
2111 struct vb2_buffer *vb;
2112 struct s5p_jpeg_addr jpeg_addr = {};
2113 u32 pix_size, padding_bytes = 0;
2114
2115 jpeg_addr.cb = 0;
2116 jpeg_addr.cr = 0;
2117
2118 pix_size = ctx->cap_q.w * ctx->cap_q.h;
2119
2120 if (ctx->mode == S5P_JPEG_ENCODE) {
2121 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2122 fmt = ctx->out_q.fmt;
2123 if (ctx->out_q.w % 2 && fmt->h_align > 0)
2124 padding_bytes = ctx->out_q.h;
2125 } else {
2126 fmt = ctx->cap_q.fmt;
2127 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2128 }
2129
2130 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
2131
2132 if (fmt->colplanes == 2) {
2133 jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;
2134 } else if (fmt->colplanes == 3) {
2135 jpeg_addr.cb = jpeg_addr.y + pix_size;
2136 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
2137 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
2138 else
2139 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
2140 }
2141
2142 exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);
2143}
2144
2145static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
2146{
2147 struct s5p_jpeg *jpeg = ctx->jpeg;
2148 struct vb2_buffer *vb;
2149 unsigned int jpeg_addr = 0;
2150
2151 if (ctx->mode == S5P_JPEG_ENCODE)
2152 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2153 else
2154 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2155
2156 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
2157 if (jpeg->variant->version == SJPEG_EXYNOS5433 &&
2158 ctx->mode == S5P_JPEG_DECODE)
2159 jpeg_addr += ctx->out_q.sos;
2160 exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
2161}
2162
2163static inline void exynos4_jpeg_set_img_fmt(void __iomem *base,
2164 unsigned int img_fmt)
2165{
2166 __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS4);
2167}
2168
2169static inline void exynos5433_jpeg_set_img_fmt(void __iomem *base,
2170 unsigned int img_fmt)
2171{
2172 __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS5433);
2173}
2174
2175static inline void exynos4_jpeg_set_enc_out_fmt(void __iomem *base,
2176 unsigned int out_fmt)
2177{
2178 __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS4);
2179}
2180
2181static inline void exynos5433_jpeg_set_enc_out_fmt(void __iomem *base,
2182 unsigned int out_fmt)
2183{
2184 __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS5433);
2185}
2186
2187static void exynos4_jpeg_device_run(void *priv)
2188{
2189 struct s5p_jpeg_ctx *ctx = priv;
2190 struct s5p_jpeg *jpeg = ctx->jpeg;
2191 unsigned int bitstream_size;
2192 unsigned long flags;
2193
2194 spin_lock_irqsave(&jpeg->slock, flags);
2195
2196 if (ctx->mode == S5P_JPEG_ENCODE) {
2197 exynos4_jpeg_sw_reset(jpeg->regs);
2198 exynos4_jpeg_set_interrupt(jpeg->regs, jpeg->variant->version);
2199 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
2200
2201 exynos4_jpeg_set_huff_tbl(jpeg->regs);
2202
2203
2204
2205
2206
2207 exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
2208 exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
2209
2210 exynos4_jpeg_set_encode_tbl_select(jpeg->regs,
2211 ctx->compr_quality);
2212 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
2213 ctx->cap_q.h);
2214
2215 if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) {
2216 exynos4_jpeg_set_enc_out_fmt(jpeg->regs,
2217 ctx->subsampling);
2218 exynos4_jpeg_set_img_fmt(jpeg->regs,
2219 ctx->out_q.fmt->fourcc);
2220 } else {
2221 exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
2222 ctx->subsampling);
2223 exynos5433_jpeg_set_img_fmt(jpeg->regs,
2224 ctx->out_q.fmt->fourcc);
2225 }
2226 exynos4_jpeg_set_img_addr(ctx);
2227 exynos4_jpeg_set_jpeg_addr(ctx);
2228 exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
2229 ctx->out_q.fmt->fourcc);
2230 } else {
2231 exynos4_jpeg_sw_reset(jpeg->regs);
2232 exynos4_jpeg_set_interrupt(jpeg->regs,
2233 jpeg->variant->version);
2234 exynos4_jpeg_set_img_addr(ctx);
2235 exynos4_jpeg_set_jpeg_addr(ctx);
2236
2237 if (jpeg->variant->version == SJPEG_EXYNOS5433) {
2238 exynos4_jpeg_parse_huff_tbl(ctx);
2239 exynos4_jpeg_parse_decode_h_tbl(ctx);
2240
2241 exynos4_jpeg_parse_q_tbl(ctx);
2242 exynos4_jpeg_parse_decode_q_tbl(ctx);
2243
2244 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
2245
2246 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
2247 ctx->cap_q.h);
2248 exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
2249 ctx->subsampling);
2250 exynos5433_jpeg_set_img_fmt(jpeg->regs,
2251 ctx->cap_q.fmt->fourcc);
2252 bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 16);
2253 } else {
2254 exynos4_jpeg_set_img_fmt(jpeg->regs,
2255 ctx->cap_q.fmt->fourcc);
2256 bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
2257 }
2258
2259 exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
2260 }
2261
2262 exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
2263
2264 spin_unlock_irqrestore(&jpeg->slock, flags);
2265}
2266
2267static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
2268{
2269 struct s5p_jpeg *jpeg = ctx->jpeg;
2270 struct s5p_jpeg_fmt *fmt;
2271 struct vb2_buffer *vb;
2272 struct s5p_jpeg_addr jpeg_addr = {};
2273 u32 pix_size;
2274
2275 pix_size = ctx->cap_q.w * ctx->cap_q.h;
2276
2277 if (ctx->mode == S5P_JPEG_ENCODE) {
2278 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2279 fmt = ctx->out_q.fmt;
2280 } else {
2281 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2282 fmt = ctx->cap_q.fmt;
2283 }
2284
2285 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
2286
2287 if (fmt->colplanes == 2) {
2288 jpeg_addr.cb = jpeg_addr.y + pix_size;
2289 } else if (fmt->colplanes == 3) {
2290 jpeg_addr.cb = jpeg_addr.y + pix_size;
2291 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
2292 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
2293 else
2294 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
2295 }
2296
2297 exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);
2298}
2299
2300static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
2301{
2302 struct s5p_jpeg *jpeg = ctx->jpeg;
2303 struct vb2_buffer *vb;
2304 unsigned int jpeg_addr = 0;
2305
2306 if (ctx->mode == S5P_JPEG_ENCODE)
2307 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2308 else
2309 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2310
2311 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
2312 exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);
2313}
2314
2315static void exynos3250_jpeg_device_run(void *priv)
2316{
2317 struct s5p_jpeg_ctx *ctx = priv;
2318 struct s5p_jpeg *jpeg = ctx->jpeg;
2319 unsigned long flags;
2320
2321 spin_lock_irqsave(&ctx->jpeg->slock, flags);
2322
2323 exynos3250_jpeg_reset(jpeg->regs);
2324 exynos3250_jpeg_set_dma_num(jpeg->regs);
2325 exynos3250_jpeg_poweron(jpeg->regs);
2326 exynos3250_jpeg_clk_set(jpeg->regs);
2327 exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);
2328
2329 if (ctx->mode == S5P_JPEG_ENCODE) {
2330 exynos3250_jpeg_input_raw_fmt(jpeg->regs,
2331 ctx->out_q.fmt->fourcc);
2332 exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);
2333
2334
2335
2336
2337
2338 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
2339 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
2340
2341 exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);
2342
2343 exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
2344 exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
2345
2346
2347
2348
2349 if (jpeg->variant->htbl_reinit) {
2350 s5p_jpeg_set_hdctbl(jpeg->regs);
2351 s5p_jpeg_set_hdctblg(jpeg->regs);
2352 s5p_jpeg_set_hactbl(jpeg->regs);
2353 s5p_jpeg_set_hactblg(jpeg->regs);
2354 }
2355
2356
2357 exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
2358 exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
2359 exynos3250_jpeg_htbl_ac(jpeg->regs, 2);
2360 exynos3250_jpeg_htbl_dc(jpeg->regs, 2);
2361 exynos3250_jpeg_htbl_ac(jpeg->regs, 3);
2362 exynos3250_jpeg_htbl_dc(jpeg->regs, 3);
2363
2364 exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);
2365 exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);
2366 exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,
2367 ctx->out_q.w);
2368 exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,
2369 ctx->crop_rect.top);
2370 exynos3250_jpeg_set_img_addr(ctx);
2371 exynos3250_jpeg_set_jpeg_addr(ctx);
2372 exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
2373
2374
2375 exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);
2376
2377 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||
2378 ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||
2379 ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
2380 exynos3250_jpeg_set_y16(jpeg->regs, true);
2381 } else {
2382 exynos3250_jpeg_set_img_addr(ctx);
2383 exynos3250_jpeg_set_jpeg_addr(ctx);
2384 exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,
2385 ctx->cap_q.w);
2386 exynos3250_jpeg_offset(jpeg->regs, 0, 0);
2387 exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,
2388 ctx->scale_factor);
2389 exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);
2390 exynos3250_jpeg_output_raw_fmt(jpeg->regs,
2391 ctx->cap_q.fmt->fourcc);
2392 }
2393
2394 exynos3250_jpeg_interrupts_enable(jpeg->regs);
2395
2396
2397 exynos3250_jpeg_coef(jpeg->regs, ctx->mode);
2398
2399 exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);
2400 jpeg->irq_status = 0;
2401 exynos3250_jpeg_start(jpeg->regs);
2402
2403 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
2404}
2405
2406static int s5p_jpeg_job_ready(void *priv)
2407{
2408 struct s5p_jpeg_ctx *ctx = priv;
2409
2410 if (ctx->mode == S5P_JPEG_DECODE)
2411 return ctx->hdr_parsed;
2412 return 1;
2413}
2414
2415static void s5p_jpeg_job_abort(void *priv)
2416{
2417}
2418
2419static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
2420 .device_run = s5p_jpeg_device_run,
2421 .job_ready = s5p_jpeg_job_ready,
2422 .job_abort = s5p_jpeg_job_abort,
2423};
2424
2425static struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {
2426 .device_run = exynos3250_jpeg_device_run,
2427 .job_ready = s5p_jpeg_job_ready,
2428 .job_abort = s5p_jpeg_job_abort,
2429};
2430
2431static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
2432 .device_run = exynos4_jpeg_device_run,
2433 .job_ready = s5p_jpeg_job_ready,
2434 .job_abort = s5p_jpeg_job_abort,
2435};
2436
2437
2438
2439
2440
2441
2442
2443static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
2444 unsigned int *nbuffers, unsigned int *nplanes,
2445 unsigned int sizes[], struct device *alloc_devs[])
2446{
2447 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
2448 struct s5p_jpeg_q_data *q_data = NULL;
2449 unsigned int size, count = *nbuffers;
2450
2451 q_data = get_q_data(ctx, vq->type);
2452 BUG_ON(q_data == NULL);
2453
2454 size = q_data->size;
2455
2456
2457
2458
2459
2460 if (ctx->mode == S5P_JPEG_DECODE)
2461 count = 1;
2462
2463 *nbuffers = count;
2464 *nplanes = 1;
2465 sizes[0] = size;
2466
2467 return 0;
2468}
2469
2470static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
2471{
2472 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2473 struct s5p_jpeg_q_data *q_data = NULL;
2474
2475 q_data = get_q_data(ctx, vb->vb2_queue->type);
2476 BUG_ON(q_data == NULL);
2477
2478 if (vb2_plane_size(vb, 0) < q_data->size) {
2479 pr_err("%s data will not fit into plane (%lu < %lu)\n",
2480 __func__, vb2_plane_size(vb, 0),
2481 (long)q_data->size);
2482 return -EINVAL;
2483 }
2484
2485 vb2_set_plane_payload(vb, 0, q_data->size);
2486
2487 return 0;
2488}
2489
2490static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
2491{
2492 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
2493 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2494
2495 if (ctx->mode == S5P_JPEG_DECODE &&
2496 vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
2497 struct s5p_jpeg_q_data tmp, *q_data;
2498
2499 ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
2500 (unsigned long)vb2_plane_vaddr(vb, 0),
2501 min((unsigned long)ctx->out_q.size,
2502 vb2_get_plane_payload(vb, 0)), ctx);
2503 if (!ctx->hdr_parsed) {
2504 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
2505 return;
2506 }
2507
2508 q_data = &ctx->out_q;
2509 q_data->w = tmp.w;
2510 q_data->h = tmp.h;
2511 q_data->sos = tmp.sos;
2512 memcpy(q_data->dht.marker, tmp.dht.marker,
2513 sizeof(tmp.dht.marker));
2514 memcpy(q_data->dht.len, tmp.dht.len, sizeof(tmp.dht.len));
2515 q_data->dht.n = tmp.dht.n;
2516 memcpy(q_data->dqt.marker, tmp.dqt.marker,
2517 sizeof(tmp.dqt.marker));
2518 memcpy(q_data->dqt.len, tmp.dqt.len, sizeof(tmp.dqt.len));
2519 q_data->dqt.n = tmp.dqt.n;
2520 q_data->sof = tmp.sof;
2521 q_data->sof_len = tmp.sof_len;
2522
2523 q_data = &ctx->cap_q;
2524 q_data->w = tmp.w;
2525 q_data->h = tmp.h;
2526 }
2527
2528 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
2529}
2530
2531static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
2532{
2533 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
2534 int ret;
2535
2536 ret = pm_runtime_get_sync(ctx->jpeg->dev);
2537
2538 return ret > 0 ? 0 : ret;
2539}
2540
2541static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
2542{
2543 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
2544
2545 pm_runtime_put(ctx->jpeg->dev);
2546}
2547
2548static const struct vb2_ops s5p_jpeg_qops = {
2549 .queue_setup = s5p_jpeg_queue_setup,
2550 .buf_prepare = s5p_jpeg_buf_prepare,
2551 .buf_queue = s5p_jpeg_buf_queue,
2552 .wait_prepare = vb2_ops_wait_prepare,
2553 .wait_finish = vb2_ops_wait_finish,
2554 .start_streaming = s5p_jpeg_start_streaming,
2555 .stop_streaming = s5p_jpeg_stop_streaming,
2556};
2557
2558static int queue_init(void *priv, struct vb2_queue *src_vq,
2559 struct vb2_queue *dst_vq)
2560{
2561 struct s5p_jpeg_ctx *ctx = priv;
2562 int ret;
2563
2564 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2565 src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
2566 src_vq->drv_priv = ctx;
2567 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
2568 src_vq->ops = &s5p_jpeg_qops;
2569 src_vq->mem_ops = &vb2_dma_contig_memops;
2570 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
2571 src_vq->lock = &ctx->jpeg->lock;
2572 src_vq->dev = ctx->jpeg->dev;
2573
2574 ret = vb2_queue_init(src_vq);
2575 if (ret)
2576 return ret;
2577
2578 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2579 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
2580 dst_vq->drv_priv = ctx;
2581 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
2582 dst_vq->ops = &s5p_jpeg_qops;
2583 dst_vq->mem_ops = &vb2_dma_contig_memops;
2584 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
2585 dst_vq->lock = &ctx->jpeg->lock;
2586 dst_vq->dev = ctx->jpeg->dev;
2587
2588 return vb2_queue_init(dst_vq);
2589}
2590
2591
2592
2593
2594
2595
2596
2597static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
2598{
2599 struct s5p_jpeg *jpeg = dev_id;
2600 struct s5p_jpeg_ctx *curr_ctx;
2601 struct vb2_v4l2_buffer *src_buf, *dst_buf;
2602 unsigned long payload_size = 0;
2603 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
2604 bool enc_jpeg_too_large = false;
2605 bool timer_elapsed = false;
2606 bool op_completed = false;
2607
2608 spin_lock(&jpeg->slock);
2609
2610 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2611
2612 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2613 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2614
2615 if (curr_ctx->mode == S5P_JPEG_ENCODE)
2616 enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);
2617 timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);
2618 op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);
2619 if (curr_ctx->mode == S5P_JPEG_DECODE)
2620 op_completed = op_completed &&
2621 s5p_jpeg_stream_stat_ok(jpeg->regs);
2622
2623 if (enc_jpeg_too_large) {
2624 state = VB2_BUF_STATE_ERROR;
2625 s5p_jpeg_clear_enc_stream_stat(jpeg->regs);
2626 } else if (timer_elapsed) {
2627 state = VB2_BUF_STATE_ERROR;
2628 s5p_jpeg_clear_timer_stat(jpeg->regs);
2629 } else if (!op_completed) {
2630 state = VB2_BUF_STATE_ERROR;
2631 } else {
2632 payload_size = s5p_jpeg_compressed_size(jpeg->regs);
2633 }
2634
2635 dst_buf->timecode = src_buf->timecode;
2636 dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
2637 dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
2638 dst_buf->flags |=
2639 src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
2640
2641 v4l2_m2m_buf_done(src_buf, state);
2642 if (curr_ctx->mode == S5P_JPEG_ENCODE)
2643 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
2644 v4l2_m2m_buf_done(dst_buf, state);
2645 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
2646
2647 curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);
2648 spin_unlock(&jpeg->slock);
2649
2650 s5p_jpeg_clear_int(jpeg->regs);
2651
2652 return IRQ_HANDLED;
2653}
2654
2655static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
2656{
2657 unsigned int int_status;
2658 struct vb2_v4l2_buffer *src_vb, *dst_vb;
2659 struct s5p_jpeg *jpeg = priv;
2660 struct s5p_jpeg_ctx *curr_ctx;
2661 unsigned long payload_size = 0;
2662
2663 spin_lock(&jpeg->slock);
2664
2665 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2666
2667 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2668 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2669
2670 int_status = exynos4_jpeg_get_int_status(jpeg->regs);
2671
2672 if (int_status) {
2673 switch (int_status & 0x1f) {
2674 case 0x1:
2675 jpeg->irq_ret = ERR_PROT;
2676 break;
2677 case 0x2:
2678 jpeg->irq_ret = OK_ENC_OR_DEC;
2679 break;
2680 case 0x4:
2681 jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;
2682 break;
2683 case 0x8:
2684 jpeg->irq_ret = ERR_MULTI_SCAN;
2685 break;
2686 case 0x10:
2687 jpeg->irq_ret = ERR_FRAME;
2688 break;
2689 default:
2690 jpeg->irq_ret = ERR_UNKNOWN;
2691 break;
2692 }
2693 } else {
2694 jpeg->irq_ret = ERR_UNKNOWN;
2695 }
2696
2697 if (jpeg->irq_ret == OK_ENC_OR_DEC) {
2698 if (curr_ctx->mode == S5P_JPEG_ENCODE) {
2699 payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
2700 vb2_set_plane_payload(&dst_vb->vb2_buf,
2701 0, payload_size);
2702 }
2703 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
2704 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
2705 } else {
2706 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
2707 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
2708 }
2709
2710 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
2711 if (jpeg->variant->version == SJPEG_EXYNOS4)
2712 curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
2713
2714 spin_unlock(&jpeg->slock);
2715 return IRQ_HANDLED;
2716}
2717
2718static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
2719{
2720 struct s5p_jpeg *jpeg = dev_id;
2721 struct s5p_jpeg_ctx *curr_ctx;
2722 struct vb2_v4l2_buffer *src_buf, *dst_buf;
2723 unsigned long payload_size = 0;
2724 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
2725 bool interrupt_timeout = false;
2726 u32 irq_status;
2727
2728 spin_lock(&jpeg->slock);
2729
2730 irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);
2731 if (irq_status & EXYNOS3250_TIMER_INT_STAT) {
2732 exynos3250_jpeg_clear_timer_status(jpeg->regs);
2733 interrupt_timeout = true;
2734 dev_err(jpeg->dev, "Interrupt timeout occurred.\n");
2735 }
2736
2737 irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);
2738 exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);
2739
2740 jpeg->irq_status |= irq_status;
2741
2742 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2743
2744 if (!curr_ctx)
2745 goto exit_unlock;
2746
2747 if ((irq_status & EXYNOS3250_HEADER_STAT) &&
2748 (curr_ctx->mode == S5P_JPEG_DECODE)) {
2749 exynos3250_jpeg_rstart(jpeg->regs);
2750 goto exit_unlock;
2751 }
2752
2753 if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |
2754 EXYNOS3250_WDMA_DONE |
2755 EXYNOS3250_RDMA_DONE |
2756 EXYNOS3250_RESULT_STAT))
2757 payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);
2758 else if (interrupt_timeout)
2759 state = VB2_BUF_STATE_ERROR;
2760 else
2761 goto exit_unlock;
2762
2763 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2764 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2765
2766 dst_buf->timecode = src_buf->timecode;
2767 dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
2768
2769 v4l2_m2m_buf_done(src_buf, state);
2770 if (curr_ctx->mode == S5P_JPEG_ENCODE)
2771 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
2772 v4l2_m2m_buf_done(dst_buf, state);
2773 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
2774
2775 curr_ctx->subsampling =
2776 exynos3250_jpeg_get_subsampling_mode(jpeg->regs);
2777exit_unlock:
2778 spin_unlock(&jpeg->slock);
2779 return IRQ_HANDLED;
2780}
2781
2782static void *jpeg_get_drv_data(struct device *dev);
2783
2784
2785
2786
2787
2788
2789
2790static int s5p_jpeg_probe(struct platform_device *pdev)
2791{
2792 struct s5p_jpeg *jpeg;
2793 struct resource *res;
2794 int i, ret;
2795
2796
2797 jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
2798 if (!jpeg)
2799 return -ENOMEM;
2800
2801 jpeg->variant = jpeg_get_drv_data(&pdev->dev);
2802
2803 mutex_init(&jpeg->lock);
2804 spin_lock_init(&jpeg->slock);
2805 jpeg->dev = &pdev->dev;
2806
2807
2808 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2809
2810 jpeg->regs = devm_ioremap_resource(&pdev->dev, res);
2811 if (IS_ERR(jpeg->regs))
2812 return PTR_ERR(jpeg->regs);
2813
2814
2815 jpeg->irq = ret = platform_get_irq(pdev, 0);
2816 if (ret < 0) {
2817 dev_err(&pdev->dev, "cannot find IRQ\n");
2818 return ret;
2819 }
2820
2821 ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,
2822 0, dev_name(&pdev->dev), jpeg);
2823 if (ret) {
2824 dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
2825 return ret;
2826 }
2827
2828
2829 for (i = 0; i < jpeg->variant->num_clocks; i++) {
2830 jpeg->clocks[i] = devm_clk_get(&pdev->dev,
2831 jpeg->variant->clk_names[i]);
2832 if (IS_ERR(jpeg->clocks[i])) {
2833 dev_err(&pdev->dev, "failed to get clock: %s\n",
2834 jpeg->variant->clk_names[i]);
2835 return PTR_ERR(jpeg->clocks[i]);
2836 }
2837 }
2838
2839
2840 ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
2841 if (ret) {
2842 dev_err(&pdev->dev, "Failed to register v4l2 device\n");
2843 return ret;
2844 }
2845
2846
2847 jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
2848 if (IS_ERR(jpeg->m2m_dev)) {
2849 v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
2850 ret = PTR_ERR(jpeg->m2m_dev);
2851 goto device_register_rollback;
2852 }
2853
2854 vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
2855
2856
2857 jpeg->vfd_encoder = video_device_alloc();
2858 if (!jpeg->vfd_encoder) {
2859 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2860 ret = -ENOMEM;
2861 goto m2m_init_rollback;
2862 }
2863 snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),
2864 "%s-enc", S5P_JPEG_M2M_NAME);
2865 jpeg->vfd_encoder->fops = &s5p_jpeg_fops;
2866 jpeg->vfd_encoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2867 jpeg->vfd_encoder->minor = -1;
2868 jpeg->vfd_encoder->release = video_device_release;
2869 jpeg->vfd_encoder->lock = &jpeg->lock;
2870 jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev;
2871 jpeg->vfd_encoder->vfl_dir = VFL_DIR_M2M;
2872
2873 ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
2874 if (ret) {
2875 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
2876 video_device_release(jpeg->vfd_encoder);
2877 goto m2m_init_rollback;
2878 }
2879
2880 video_set_drvdata(jpeg->vfd_encoder, jpeg);
2881 v4l2_info(&jpeg->v4l2_dev,
2882 "encoder device registered as /dev/video%d\n",
2883 jpeg->vfd_encoder->num);
2884
2885
2886 jpeg->vfd_decoder = video_device_alloc();
2887 if (!jpeg->vfd_decoder) {
2888 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2889 ret = -ENOMEM;
2890 goto enc_vdev_register_rollback;
2891 }
2892 snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),
2893 "%s-dec", S5P_JPEG_M2M_NAME);
2894 jpeg->vfd_decoder->fops = &s5p_jpeg_fops;
2895 jpeg->vfd_decoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2896 jpeg->vfd_decoder->minor = -1;
2897 jpeg->vfd_decoder->release = video_device_release;
2898 jpeg->vfd_decoder->lock = &jpeg->lock;
2899 jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev;
2900 jpeg->vfd_decoder->vfl_dir = VFL_DIR_M2M;
2901
2902 ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
2903 if (ret) {
2904 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
2905 video_device_release(jpeg->vfd_decoder);
2906 goto enc_vdev_register_rollback;
2907 }
2908
2909 video_set_drvdata(jpeg->vfd_decoder, jpeg);
2910 v4l2_info(&jpeg->v4l2_dev,
2911 "decoder device registered as /dev/video%d\n",
2912 jpeg->vfd_decoder->num);
2913
2914
2915 platform_set_drvdata(pdev, jpeg);
2916
2917 pm_runtime_enable(&pdev->dev);
2918
2919 v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
2920
2921 return 0;
2922
2923enc_vdev_register_rollback:
2924 video_unregister_device(jpeg->vfd_encoder);
2925
2926m2m_init_rollback:
2927 v4l2_m2m_release(jpeg->m2m_dev);
2928
2929device_register_rollback:
2930 v4l2_device_unregister(&jpeg->v4l2_dev);
2931
2932 return ret;
2933}
2934
2935static int s5p_jpeg_remove(struct platform_device *pdev)
2936{
2937 struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
2938 int i;
2939
2940 pm_runtime_disable(jpeg->dev);
2941
2942 video_unregister_device(jpeg->vfd_decoder);
2943 video_unregister_device(jpeg->vfd_encoder);
2944 vb2_dma_contig_clear_max_seg_size(&pdev->dev);
2945 v4l2_m2m_release(jpeg->m2m_dev);
2946 v4l2_device_unregister(&jpeg->v4l2_dev);
2947
2948 if (!pm_runtime_status_suspended(&pdev->dev)) {
2949 for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
2950 clk_disable_unprepare(jpeg->clocks[i]);
2951 }
2952
2953 return 0;
2954}
2955
2956#ifdef CONFIG_PM
2957static int s5p_jpeg_runtime_suspend(struct device *dev)
2958{
2959 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
2960 int i;
2961
2962 for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
2963 clk_disable_unprepare(jpeg->clocks[i]);
2964
2965 return 0;
2966}
2967
2968static int s5p_jpeg_runtime_resume(struct device *dev)
2969{
2970 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
2971 unsigned long flags;
2972 int i, ret;
2973
2974 for (i = 0; i < jpeg->variant->num_clocks; i++) {
2975 ret = clk_prepare_enable(jpeg->clocks[i]);
2976 if (ret) {
2977 while (--i > 0)
2978 clk_disable_unprepare(jpeg->clocks[i]);
2979 return ret;
2980 }
2981 }
2982
2983 spin_lock_irqsave(&jpeg->slock, flags);
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993 if (!jpeg->variant->htbl_reinit) {
2994 s5p_jpeg_set_hdctbl(jpeg->regs);
2995 s5p_jpeg_set_hdctblg(jpeg->regs);
2996 s5p_jpeg_set_hactbl(jpeg->regs);
2997 s5p_jpeg_set_hactblg(jpeg->regs);
2998 }
2999
3000 spin_unlock_irqrestore(&jpeg->slock, flags);
3001
3002 return 0;
3003}
3004#endif
3005
3006static const struct dev_pm_ops s5p_jpeg_pm_ops = {
3007 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
3008 pm_runtime_force_resume)
3009 SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume,
3010 NULL)
3011};
3012
3013static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
3014 .version = SJPEG_S5P,
3015 .jpeg_irq = s5p_jpeg_irq,
3016 .m2m_ops = &s5p_jpeg_m2m_ops,
3017 .fmt_ver_flag = SJPEG_FMT_FLAG_S5P,
3018 .clk_names = {"jpeg"},
3019 .num_clocks = 1,
3020};
3021
3022static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
3023 .version = SJPEG_EXYNOS3250,
3024 .jpeg_irq = exynos3250_jpeg_irq,
3025 .m2m_ops = &exynos3250_jpeg_m2m_ops,
3026 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250,
3027 .hw3250_compat = 1,
3028 .clk_names = {"jpeg", "sclk"},
3029 .num_clocks = 2,
3030};
3031
3032static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
3033 .version = SJPEG_EXYNOS4,
3034 .jpeg_irq = exynos4_jpeg_irq,
3035 .m2m_ops = &exynos4_jpeg_m2m_ops,
3036 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
3037 .htbl_reinit = 1,
3038 .clk_names = {"jpeg"},
3039 .num_clocks = 1,
3040 .hw_ex4_compat = 1,
3041};
3042
3043static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
3044 .version = SJPEG_EXYNOS5420,
3045 .jpeg_irq = exynos3250_jpeg_irq,
3046 .m2m_ops = &exynos3250_jpeg_m2m_ops,
3047 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250,
3048 .hw3250_compat = 1,
3049 .htbl_reinit = 1,
3050 .clk_names = {"jpeg"},
3051 .num_clocks = 1,
3052};
3053
3054static struct s5p_jpeg_variant exynos5433_jpeg_drvdata = {
3055 .version = SJPEG_EXYNOS5433,
3056 .jpeg_irq = exynos4_jpeg_irq,
3057 .m2m_ops = &exynos4_jpeg_m2m_ops,
3058 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
3059 .htbl_reinit = 1,
3060 .clk_names = {"pclk", "aclk", "aclk_xiu", "sclk"},
3061 .num_clocks = 4,
3062 .hw_ex4_compat = 1,
3063};
3064
3065static const struct of_device_id samsung_jpeg_match[] = {
3066 {
3067 .compatible = "samsung,s5pv210-jpeg",
3068 .data = &s5p_jpeg_drvdata,
3069 }, {
3070 .compatible = "samsung,exynos3250-jpeg",
3071 .data = &exynos3250_jpeg_drvdata,
3072 }, {
3073 .compatible = "samsung,exynos4210-jpeg",
3074 .data = &exynos4_jpeg_drvdata,
3075 }, {
3076 .compatible = "samsung,exynos4212-jpeg",
3077 .data = &exynos4_jpeg_drvdata,
3078 }, {
3079 .compatible = "samsung,exynos5420-jpeg",
3080 .data = &exynos5420_jpeg_drvdata,
3081 }, {
3082 .compatible = "samsung,exynos5433-jpeg",
3083 .data = &exynos5433_jpeg_drvdata,
3084 },
3085 {},
3086};
3087
3088MODULE_DEVICE_TABLE(of, samsung_jpeg_match);
3089
3090static void *jpeg_get_drv_data(struct device *dev)
3091{
3092 struct s5p_jpeg_variant *driver_data = NULL;
3093 const struct of_device_id *match;
3094
3095 if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
3096 return &s5p_jpeg_drvdata;
3097
3098 match = of_match_node(samsung_jpeg_match, dev->of_node);
3099
3100 if (match)
3101 driver_data = (struct s5p_jpeg_variant *)match->data;
3102
3103 return driver_data;
3104}
3105
3106static struct platform_driver s5p_jpeg_driver = {
3107 .probe = s5p_jpeg_probe,
3108 .remove = s5p_jpeg_remove,
3109 .driver = {
3110 .of_match_table = of_match_ptr(samsung_jpeg_match),
3111 .name = S5P_JPEG_M2M_NAME,
3112 .pm = &s5p_jpeg_pm_ops,
3113 },
3114};
3115
3116module_platform_driver(s5p_jpeg_driver);
3117
3118MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
3119MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
3120MODULE_DESCRIPTION("Samsung JPEG codec driver");
3121MODULE_LICENSE("GPL");
3122