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