[media] s5p-jpeg: Allow for wider JPEG subsampling scope for Exynos4x12 encoder
[deliverable/linux.git] / drivers / media / platform / s5p-jpeg / jpeg-core.c
CommitLineData
2c3fb08b 1/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c
bb677f3a 2 *
80529ae5 3 * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd.
bb677f3a
AP
4 * http://www.samsung.com
5 *
6 * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
80529ae5 7 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
bb677f3a
AP
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/clk.h>
15#include <linux/err.h>
16#include <linux/gfp.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
f7074ab3 21#include <linux/of.h>
bb677f3a
AP
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-core.h>
30#include <media/videobuf2-dma-contig.h>
31
32#include "jpeg-core.h"
9f7b62d9 33#include "jpeg-hw-s5p.h"
80529ae5
JA
34#include "jpeg-hw-exynos4.h"
35#include "jpeg-regs.h"
bb677f3a 36
80529ae5 37static struct s5p_jpeg_fmt sjpeg_formats[] = {
bb677f3a 38 {
fb6f8c02
AP
39 .name = "JPEG JFIF",
40 .fourcc = V4L2_PIX_FMT_JPEG,
80529ae5
JA
41 .flags = SJPEG_FMT_FLAG_ENC_CAPTURE |
42 SJPEG_FMT_FLAG_DEC_OUTPUT |
43 SJPEG_FMT_FLAG_S5P |
44 SJPEG_FMT_FLAG_EXYNOS4,
45 },
46 {
47 .name = "YUV 4:2:2 packed, YCbYCr",
48 .fourcc = V4L2_PIX_FMT_YUYV,
49 .depth = 16,
fb6f8c02 50 .colplanes = 1,
80529ae5
JA
51 .h_align = 4,
52 .v_align = 3,
53 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
54 SJPEG_FMT_FLAG_DEC_CAPTURE |
55 SJPEG_FMT_FLAG_S5P |
56 SJPEG_FMT_NON_RGB,
57 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
bb677f3a
AP
58 },
59 {
60 .name = "YUV 4:2:2 packed, YCbYCr",
61 .fourcc = V4L2_PIX_FMT_YUYV,
62 .depth = 16,
63 .colplanes = 1,
80529ae5
JA
64 .h_align = 1,
65 .v_align = 0,
66 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
67 SJPEG_FMT_FLAG_DEC_CAPTURE |
68 SJPEG_FMT_FLAG_EXYNOS4 |
69 SJPEG_FMT_NON_RGB,
70 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
71 },
72 {
73 .name = "YUV 4:2:2 packed, YCrYCb",
74 .fourcc = V4L2_PIX_FMT_YVYU,
75 .depth = 16,
76 .colplanes = 1,
77 .h_align = 1,
78 .v_align = 0,
79 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
80 SJPEG_FMT_FLAG_DEC_CAPTURE |
81 SJPEG_FMT_FLAG_EXYNOS4 |
82 SJPEG_FMT_NON_RGB,
83 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
bb677f3a
AP
84 },
85 {
86 .name = "RGB565",
87 .fourcc = V4L2_PIX_FMT_RGB565,
88 .depth = 16,
89 .colplanes = 1,
80529ae5
JA
90 .h_align = 0,
91 .v_align = 0,
92 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
93 SJPEG_FMT_FLAG_DEC_CAPTURE |
94 SJPEG_FMT_FLAG_EXYNOS4 |
95 SJPEG_FMT_RGB,
96 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
97 },
98 {
99 .name = "RGB565",
100 .fourcc = V4L2_PIX_FMT_RGB565,
101 .depth = 16,
102 .colplanes = 1,
103 .h_align = 0,
104 .v_align = 0,
105 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
106 SJPEG_FMT_FLAG_S5P |
107 SJPEG_FMT_RGB,
108 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
109 },
110 {
111 .name = "ARGB8888, 32 bpp",
112 .fourcc = V4L2_PIX_FMT_RGB32,
113 .depth = 32,
114 .colplanes = 1,
115 .h_align = 0,
116 .v_align = 0,
117 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
118 SJPEG_FMT_FLAG_DEC_CAPTURE |
119 SJPEG_FMT_FLAG_EXYNOS4 |
120 SJPEG_FMT_RGB,
121 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
122 },
123 {
124 .name = "YUV 4:4:4 planar, Y/CbCr",
125 .fourcc = V4L2_PIX_FMT_NV24,
126 .depth = 24,
127 .colplanes = 2,
128 .h_align = 0,
129 .v_align = 0,
130 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
131 SJPEG_FMT_FLAG_DEC_CAPTURE |
132 SJPEG_FMT_FLAG_EXYNOS4 |
133 SJPEG_FMT_NON_RGB,
134 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
135 },
136 {
137 .name = "YUV 4:4:4 planar, Y/CrCb",
138 .fourcc = V4L2_PIX_FMT_NV42,
139 .depth = 24,
140 .colplanes = 2,
141 .h_align = 0,
142 .v_align = 0,
143 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
144 SJPEG_FMT_FLAG_DEC_CAPTURE |
145 SJPEG_FMT_FLAG_EXYNOS4 |
146 SJPEG_FMT_NON_RGB,
147 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
148 },
149 {
150 .name = "YUV 4:2:2 planar, Y/CrCb",
151 .fourcc = V4L2_PIX_FMT_NV61,
152 .depth = 16,
153 .colplanes = 2,
154 .h_align = 1,
155 .v_align = 0,
156 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
157 SJPEG_FMT_FLAG_DEC_CAPTURE |
158 SJPEG_FMT_FLAG_EXYNOS4 |
159 SJPEG_FMT_NON_RGB,
160 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
bb677f3a 161 },
bb677f3a 162 {
80529ae5
JA
163 .name = "YUV 4:2:2 planar, Y/CbCr",
164 .fourcc = V4L2_PIX_FMT_NV16,
165 .depth = 16,
166 .colplanes = 2,
167 .h_align = 1,
168 .v_align = 0,
169 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
170 SJPEG_FMT_FLAG_DEC_CAPTURE |
171 SJPEG_FMT_FLAG_EXYNOS4 |
172 SJPEG_FMT_NON_RGB,
173 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
174 },
175 {
176 .name = "YUV 4:2:0 planar, Y/CbCr",
c97ba28b 177 .fourcc = V4L2_PIX_FMT_NV12,
80529ae5
JA
178 .depth = 16,
179 .colplanes = 2,
180 .h_align = 1,
181 .v_align = 1,
182 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
183 SJPEG_FMT_FLAG_DEC_CAPTURE |
184 SJPEG_FMT_FLAG_EXYNOS4 |
185 SJPEG_FMT_NON_RGB,
186 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
bb677f3a
AP
187 },
188 {
80529ae5
JA
189 .name = "YUV 4:2:0 planar, Y/CbCr",
190 .fourcc = V4L2_PIX_FMT_NV12,
bb677f3a 191 .depth = 16,
80529ae5 192 .colplanes = 4,
bb677f3a 193 .h_align = 4,
80529ae5
JA
194 .v_align = 1,
195 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
196 SJPEG_FMT_FLAG_DEC_CAPTURE |
197 SJPEG_FMT_FLAG_S5P |
198 SJPEG_FMT_NON_RGB,
199 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
bb677f3a
AP
200 },
201 {
80529ae5
JA
202 .name = "YUV 4:2:0 planar, Y/CrCb",
203 .fourcc = V4L2_PIX_FMT_NV21,
204 .depth = 12,
205 .colplanes = 2,
206 .h_align = 1,
207 .v_align = 1,
208 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
209 SJPEG_FMT_FLAG_DEC_CAPTURE |
210 SJPEG_FMT_FLAG_EXYNOS4 |
211 SJPEG_FMT_NON_RGB,
212 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
213 },
214 {
215 .name = "YUV 4:2:0 contiguous 3-planar, Y/Cb/Cr",
216 .fourcc = V4L2_PIX_FMT_YUV420,
217 .depth = 12,
218 .colplanes = 3,
219 .h_align = 1,
220 .v_align = 1,
221 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
222 SJPEG_FMT_FLAG_DEC_CAPTURE |
223 SJPEG_FMT_FLAG_EXYNOS4 |
224 SJPEG_FMT_NON_RGB,
225 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
226 },
227 {
228 .name = "Gray",
229 .fourcc = V4L2_PIX_FMT_GREY,
230 .depth = 8,
bb677f3a 231 .colplanes = 1,
80529ae5
JA
232 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
233 SJPEG_FMT_FLAG_DEC_CAPTURE |
234 SJPEG_FMT_FLAG_EXYNOS4 |
235 SJPEG_FMT_NON_RGB,
236 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
bb677f3a
AP
237 },
238};
80529ae5 239#define SJPEG_NUM_FORMATS ARRAY_SIZE(sjpeg_formats)
bb677f3a
AP
240
241static const unsigned char qtbl_luminance[4][64] = {
78e5a3ce
JA
242 {/*level 0 - high compression quality */
243 20, 16, 25, 39, 50, 46, 62, 68,
244 16, 18, 23, 38, 38, 53, 65, 68,
245 25, 23, 31, 38, 53, 65, 68, 68,
246 39, 38, 38, 53, 65, 68, 68, 68,
247 50, 38, 53, 65, 68, 68, 68, 68,
248 46, 53, 65, 68, 68, 68, 68, 68,
249 62, 65, 68, 68, 68, 68, 68, 68,
250 68, 68, 68, 68, 68, 68, 68, 68
251 },
252 {/* level 1 */
253 16, 11, 11, 16, 23, 27, 31, 30,
254 11, 12, 12, 15, 20, 23, 23, 30,
255 11, 12, 13, 16, 23, 26, 35, 47,
256 16, 15, 16, 23, 26, 37, 47, 64,
257 23, 20, 23, 26, 39, 51, 64, 64,
258 27, 23, 26, 37, 51, 64, 64, 64,
259 31, 23, 35, 47, 64, 64, 64, 64,
260 30, 30, 47, 64, 64, 64, 64, 64
bb677f3a
AP
261 },
262 {/* level 2 */
263 12, 8, 8, 12, 17, 21, 24, 23,
264 8, 9, 9, 11, 15, 19, 18, 23,
265 8, 9, 10, 12, 19, 20, 27, 36,
266 12, 11, 12, 21, 20, 28, 36, 53,
267 17, 15, 19, 20, 30, 39, 51, 59,
268 21, 19, 20, 28, 39, 51, 59, 59,
269 24, 18, 27, 36, 51, 59, 59, 59,
270 23, 23, 36, 53, 59, 59, 59, 59
271 },
78e5a3ce
JA
272 {/* level 3 - low compression quality */
273 8, 6, 6, 8, 12, 14, 16, 17,
274 6, 6, 6, 8, 10, 13, 12, 15,
275 6, 6, 7, 8, 13, 14, 18, 24,
276 8, 8, 8, 14, 13, 19, 24, 35,
277 12, 10, 13, 13, 20, 26, 34, 39,
278 14, 13, 14, 19, 26, 34, 39, 39,
279 16, 12, 18, 24, 34, 39, 39, 39,
280 17, 15, 24, 35, 39, 39, 39, 39
bb677f3a
AP
281 }
282};
283
284static const unsigned char qtbl_chrominance[4][64] = {
78e5a3ce
JA
285 {/*level 0 - high compression quality */
286 21, 25, 32, 38, 54, 68, 68, 68,
287 25, 28, 24, 38, 54, 68, 68, 68,
288 32, 24, 32, 43, 66, 68, 68, 68,
289 38, 38, 43, 53, 68, 68, 68, 68,
290 54, 54, 66, 68, 68, 68, 68, 68,
291 68, 68, 68, 68, 68, 68, 68, 68,
292 68, 68, 68, 68, 68, 68, 68, 68,
293 68, 68, 68, 68, 68, 68, 68, 68
294 },
295 {/* level 1 */
296 17, 15, 17, 21, 20, 26, 38, 48,
297 15, 19, 18, 17, 20, 26, 35, 43,
298 17, 18, 20, 22, 26, 30, 46, 53,
299 21, 17, 22, 28, 30, 39, 53, 64,
300 20, 20, 26, 30, 39, 48, 64, 64,
301 26, 26, 30, 39, 48, 63, 64, 64,
302 38, 35, 46, 53, 64, 64, 64, 64,
303 48, 43, 53, 64, 64, 64, 64, 64
bb677f3a
AP
304 },
305 {/* level 2 */
306 13, 11, 13, 16, 20, 20, 29, 37,
307 11, 14, 14, 14, 16, 20, 26, 32,
308 13, 14, 15, 17, 20, 23, 35, 40,
309 16, 14, 17, 21, 23, 30, 40, 50,
310 20, 16, 20, 23, 30, 37, 50, 59,
311 20, 20, 23, 30, 37, 48, 59, 59,
312 29, 26, 35, 40, 50, 59, 59, 59,
313 37, 32, 40, 50, 59, 59, 59, 59
314 },
78e5a3ce
JA
315 {/* level 3 - low compression quality */
316 9, 8, 9, 11, 14, 17, 19, 24,
317 8, 10, 9, 11, 14, 13, 17, 22,
318 9, 9, 13, 14, 13, 15, 23, 26,
319 11, 11, 14, 14, 15, 20, 26, 33,
320 14, 14, 13, 15, 20, 24, 33, 39,
321 17, 13, 15, 20, 24, 32, 39, 39,
322 19, 17, 23, 26, 33, 39, 39, 39,
323 24, 22, 26, 33, 39, 39, 39, 39
bb677f3a
AP
324 }
325};
326
327static const unsigned char hdctbl0[16] = {
328 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
329};
330
331static const unsigned char hdctblg0[12] = {
332 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
333};
334static const unsigned char hactbl0[16] = {
335 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
336};
337static const unsigned char hactblg0[162] = {
338 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
339 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
340 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
341 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
342 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
343 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
344 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
345 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
346 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
347 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
348 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
349 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
350 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
351 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
352 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
353 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
354 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
355 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
356 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
357 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
358 0xf9, 0xfa
359};
360
337777a4
JA
361/*
362 * Fourcc downgrade schema lookup tables for 422 and 420
363 * chroma subsampling - fourcc on each position maps on the
364 * fourcc from the table fourcc_to_dwngrd_schema_id which allows
365 * to get the most suitable fourcc counterpart for the given
366 * downgraded subsampling property.
367 */
368static const u32 subs422_fourcc_dwngrd_schema[] = {
369 V4L2_PIX_FMT_NV16,
370 V4L2_PIX_FMT_NV61,
371};
372
373static const u32 subs420_fourcc_dwngrd_schema[] = {
374 V4L2_PIX_FMT_NV12,
375 V4L2_PIX_FMT_NV21,
376 V4L2_PIX_FMT_NV12,
377 V4L2_PIX_FMT_NV21,
378 V4L2_PIX_FMT_NV12,
379 V4L2_PIX_FMT_NV21,
380 V4L2_PIX_FMT_GREY,
381 V4L2_PIX_FMT_GREY,
382 V4L2_PIX_FMT_GREY,
383 V4L2_PIX_FMT_GREY,
384};
385
386/*
387 * Lookup table for translation of a fourcc to the position
388 * of its downgraded counterpart in the *fourcc_dwngrd_schema
389 * tables.
390 */
391static const u32 fourcc_to_dwngrd_schema_id[] = {
392 V4L2_PIX_FMT_NV24,
393 V4L2_PIX_FMT_NV42,
394 V4L2_PIX_FMT_NV16,
395 V4L2_PIX_FMT_NV61,
396 V4L2_PIX_FMT_YUYV,
397 V4L2_PIX_FMT_YVYU,
398 V4L2_PIX_FMT_NV12,
399 V4L2_PIX_FMT_NV21,
400 V4L2_PIX_FMT_YUV420,
401 V4L2_PIX_FMT_GREY,
402};
403
404static int s5p_jpeg_get_dwngrd_sch_id_by_fourcc(u32 fourcc)
405{
406 int i;
407 for (i = 0; i < ARRAY_SIZE(fourcc_to_dwngrd_schema_id); ++i) {
408 if (fourcc_to_dwngrd_schema_id[i] == fourcc)
409 return i;
410 }
411
412 return -EINVAL;
413}
414
415static int s5p_jpeg_adjust_fourcc_to_subsampling(
416 enum v4l2_jpeg_chroma_subsampling subs,
417 u32 in_fourcc,
418 u32 *out_fourcc,
419 struct s5p_jpeg_ctx *ctx)
420{
421 int dwngrd_sch_id;
422
423 if (ctx->subsampling != V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
424 dwngrd_sch_id =
425 s5p_jpeg_get_dwngrd_sch_id_by_fourcc(in_fourcc);
426 if (dwngrd_sch_id < 0)
427 return -EINVAL;
428 }
429
430 switch (ctx->subsampling) {
431 case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
432 *out_fourcc = V4L2_PIX_FMT_GREY;
433 break;
434 case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
435 if (dwngrd_sch_id >
436 ARRAY_SIZE(subs420_fourcc_dwngrd_schema) - 1)
437 return -EINVAL;
438 *out_fourcc = subs420_fourcc_dwngrd_schema[dwngrd_sch_id];
439 break;
440 case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
441 if (dwngrd_sch_id >
442 ARRAY_SIZE(subs422_fourcc_dwngrd_schema) - 1)
443 return -EINVAL;
444 *out_fourcc = subs422_fourcc_dwngrd_schema[dwngrd_sch_id];
445 break;
446 default:
447 *out_fourcc = V4L2_PIX_FMT_GREY;
448 break;
449 }
450
451 return 0;
452}
453
15f4bc3b
SN
454static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
455{
456 return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
457}
458
275de24d
SN
459static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh)
460{
461 return container_of(fh, struct s5p_jpeg_ctx, fh);
462}
463
31dc0ac0
JA
464static inline void s5p_jpeg_set_qtbl(void __iomem *regs,
465 const unsigned char *qtbl,
466 unsigned long tab, int len)
bb677f3a
AP
467{
468 int i;
469
470 for (i = 0; i < len; i++)
471 writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
472}
473
31dc0ac0 474static inline void s5p_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
bb677f3a
AP
475{
476 /* this driver fills quantisation table 0 with data for luma */
31dc0ac0
JA
477 s5p_jpeg_set_qtbl(regs, qtbl_luminance[quality],
478 S5P_JPG_QTBL_CONTENT(0),
479 ARRAY_SIZE(qtbl_luminance[quality]));
bb677f3a
AP
480}
481
31dc0ac0 482static inline void s5p_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
bb677f3a
AP
483{
484 /* this driver fills quantisation table 1 with data for chroma */
31dc0ac0
JA
485 s5p_jpeg_set_qtbl(regs, qtbl_chrominance[quality],
486 S5P_JPG_QTBL_CONTENT(1),
487 ARRAY_SIZE(qtbl_chrominance[quality]));
bb677f3a
AP
488}
489
31dc0ac0
JA
490static inline void s5p_jpeg_set_htbl(void __iomem *regs,
491 const unsigned char *htbl,
492 unsigned long tab, int len)
bb677f3a
AP
493{
494 int i;
495
496 for (i = 0; i < len; i++)
497 writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
498}
499
31dc0ac0 500static inline void s5p_jpeg_set_hdctbl(void __iomem *regs)
bb677f3a
AP
501{
502 /* this driver fills table 0 for this component */
31dc0ac0
JA
503 s5p_jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0),
504 ARRAY_SIZE(hdctbl0));
bb677f3a
AP
505}
506
31dc0ac0 507static inline void s5p_jpeg_set_hdctblg(void __iomem *regs)
bb677f3a
AP
508{
509 /* this driver fills table 0 for this component */
31dc0ac0
JA
510 s5p_jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0),
511 ARRAY_SIZE(hdctblg0));
bb677f3a
AP
512}
513
31dc0ac0 514static inline void s5p_jpeg_set_hactbl(void __iomem *regs)
bb677f3a
AP
515{
516 /* this driver fills table 0 for this component */
31dc0ac0
JA
517 s5p_jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0),
518 ARRAY_SIZE(hactbl0));
bb677f3a
AP
519}
520
31dc0ac0 521static inline void s5p_jpeg_set_hactblg(void __iomem *regs)
bb677f3a
AP
522{
523 /* this driver fills table 0 for this component */
31dc0ac0
JA
524 s5p_jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0),
525 ARRAY_SIZE(hactblg0));
bb677f3a
AP
526}
527
80529ae5
JA
528static inline void exynos4_jpeg_set_tbl(void __iomem *regs,
529 const unsigned char *tbl,
530 unsigned long tab, int len)
531{
532 int i;
533 unsigned int dword;
534
535 for (i = 0; i < len; i += 4) {
536 dword = tbl[i] |
537 (tbl[i + 1] << 8) |
538 (tbl[i + 2] << 16) |
539 (tbl[i + 3] << 24);
540 writel(dword, regs + tab + i);
541 }
542}
543
544static inline void exynos4_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
545{
546 /* this driver fills quantisation table 0 with data for luma */
547 exynos4_jpeg_set_tbl(regs, qtbl_luminance[quality],
548 EXYNOS4_QTBL_CONTENT(0),
549 ARRAY_SIZE(qtbl_luminance[quality]));
550}
551
552static inline void exynos4_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
553{
554 /* this driver fills quantisation table 1 with data for chroma */
555 exynos4_jpeg_set_tbl(regs, qtbl_chrominance[quality],
556 EXYNOS4_QTBL_CONTENT(1),
557 ARRAY_SIZE(qtbl_chrominance[quality]));
558}
559
560void exynos4_jpeg_set_huff_tbl(void __iomem *base)
561{
562 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCLL,
563 ARRAY_SIZE(hdctbl0));
564 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCCL,
565 ARRAY_SIZE(hdctbl0));
566 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCLV,
567 ARRAY_SIZE(hdctblg0));
568 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCCV,
569 ARRAY_SIZE(hdctblg0));
570 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACLL,
571 ARRAY_SIZE(hactbl0));
572 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACCL,
573 ARRAY_SIZE(hactbl0));
574 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACLV,
575 ARRAY_SIZE(hactblg0));
576 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV,
577 ARRAY_SIZE(hactblg0));
578}
579
bb677f3a
AP
580/*
581 * ============================================================================
582 * Device file operations
583 * ============================================================================
584 */
585
586static int queue_init(void *priv, struct vb2_queue *src_vq,
587 struct vb2_queue *dst_vq);
80529ae5
JA
588static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
589 __u32 pixelformat, unsigned int fmt_type);
15f4bc3b 590static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx);
bb677f3a
AP
591
592static int s5p_jpeg_open(struct file *file)
593{
594 struct s5p_jpeg *jpeg = video_drvdata(file);
595 struct video_device *vfd = video_devdata(file);
596 struct s5p_jpeg_ctx *ctx;
80529ae5 597 struct s5p_jpeg_fmt *out_fmt, *cap_fmt;
275de24d 598 int ret = 0;
bb677f3a 599
b5146c96 600 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
bb677f3a
AP
601 if (!ctx)
602 return -ENOMEM;
603
b0d5cd6b
HV
604 if (mutex_lock_interruptible(&jpeg->lock)) {
605 ret = -ERESTARTSYS;
606 goto free;
607 }
608
275de24d 609 v4l2_fh_init(&ctx->fh, vfd);
15f4bc3b
SN
610 /* Use separate control handler per file handle */
611 ctx->fh.ctrl_handler = &ctx->ctrl_handler;
275de24d
SN
612 file->private_data = &ctx->fh;
613 v4l2_fh_add(&ctx->fh);
614
bb677f3a
AP
615 ctx->jpeg = jpeg;
616 if (vfd == jpeg->vfd_encoder) {
617 ctx->mode = S5P_JPEG_ENCODE;
80529ae5
JA
618 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_RGB565,
619 FMT_TYPE_OUTPUT);
620 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
621 FMT_TYPE_CAPTURE);
bb677f3a
AP
622 } else {
623 ctx->mode = S5P_JPEG_DECODE;
80529ae5
JA
624 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
625 FMT_TYPE_OUTPUT);
626 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
627 FMT_TYPE_CAPTURE);
bb677f3a
AP
628 }
629
718cf4a9
SN
630 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
631 if (IS_ERR(ctx->fh.m2m_ctx)) {
632 ret = PTR_ERR(ctx->fh.m2m_ctx);
275de24d 633 goto error;
bb677f3a
AP
634 }
635
636 ctx->out_q.fmt = out_fmt;
80529ae5
JA
637 ctx->cap_q.fmt = cap_fmt;
638
639 ret = s5p_jpeg_controls_create(ctx);
640 if (ret < 0)
641 goto error;
642
b0d5cd6b 643 mutex_unlock(&jpeg->lock);
bb677f3a 644 return 0;
275de24d
SN
645
646error:
647 v4l2_fh_del(&ctx->fh);
648 v4l2_fh_exit(&ctx->fh);
b0d5cd6b
HV
649 mutex_unlock(&jpeg->lock);
650free:
275de24d
SN
651 kfree(ctx);
652 return ret;
bb677f3a
AP
653}
654
655static int s5p_jpeg_release(struct file *file)
656{
b0d5cd6b 657 struct s5p_jpeg *jpeg = video_drvdata(file);
275de24d 658 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
bb677f3a 659
b0d5cd6b 660 mutex_lock(&jpeg->lock);
718cf4a9 661 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
15f4bc3b 662 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
275de24d
SN
663 v4l2_fh_del(&ctx->fh);
664 v4l2_fh_exit(&ctx->fh);
bb677f3a 665 kfree(ctx);
80529ae5 666 mutex_unlock(&jpeg->lock);
bb677f3a
AP
667
668 return 0;
669}
670
bb677f3a
AP
671static const struct v4l2_file_operations s5p_jpeg_fops = {
672 .owner = THIS_MODULE,
673 .open = s5p_jpeg_open,
674 .release = s5p_jpeg_release,
718cf4a9 675 .poll = v4l2_m2m_fop_poll,
bb677f3a 676 .unlocked_ioctl = video_ioctl2,
718cf4a9 677 .mmap = v4l2_m2m_fop_mmap,
bb677f3a
AP
678};
679
680/*
681 * ============================================================================
682 * video ioctl operations
683 * ============================================================================
684 */
685
686static int get_byte(struct s5p_jpeg_buffer *buf)
687{
688 if (buf->curr >= buf->size)
689 return -1;
690
691 return ((unsigned char *)buf->data)[buf->curr++];
692}
693
694static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
695{
696 unsigned int temp;
697 int byte;
698
699 byte = get_byte(buf);
700 if (byte == -1)
701 return -1;
702 temp = byte << 8;
703 byte = get_byte(buf);
704 if (byte == -1)
705 return -1;
706 *word = (unsigned int)byte | temp;
707 return 0;
708}
709
710static void skip(struct s5p_jpeg_buffer *buf, long len)
711{
712 if (len <= 0)
713 return;
714
715 while (len--)
716 get_byte(buf);
717}
718
719static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
f8433962
JA
720 unsigned long buffer, unsigned long size,
721 struct s5p_jpeg_ctx *ctx)
bb677f3a
AP
722{
723 int c, components, notfound;
f8433962 724 unsigned int height, width, word, subsampling = 0;
bb677f3a
AP
725 long length;
726 struct s5p_jpeg_buffer jpeg_buffer;
727
728 jpeg_buffer.size = size;
729 jpeg_buffer.data = buffer;
730 jpeg_buffer.curr = 0;
731
732 notfound = 1;
733 while (notfound) {
734 c = get_byte(&jpeg_buffer);
735 if (c == -1)
736 break;
737 if (c != 0xff)
738 continue;
739 do
740 c = get_byte(&jpeg_buffer);
741 while (c == 0xff);
742 if (c == -1)
743 break;
744 if (c == 0)
745 continue;
746 length = 0;
747 switch (c) {
748 /* SOF0: baseline JPEG */
749 case SOF0:
750 if (get_word_be(&jpeg_buffer, &word))
751 break;
752 if (get_byte(&jpeg_buffer) == -1)
753 break;
754 if (get_word_be(&jpeg_buffer, &height))
755 break;
756 if (get_word_be(&jpeg_buffer, &width))
757 break;
758 components = get_byte(&jpeg_buffer);
759 if (components == -1)
760 break;
761 notfound = 0;
762
f8433962
JA
763 if (components == 1) {
764 subsampling = 0x33;
765 } else {
766 skip(&jpeg_buffer, 1);
767 subsampling = get_byte(&jpeg_buffer);
768 skip(&jpeg_buffer, 1);
769 }
770
771 skip(&jpeg_buffer, components * 2);
bb677f3a
AP
772 break;
773
774 /* skip payload-less markers */
775 case RST ... RST + 7:
776 case SOI:
777 case EOI:
778 case TEM:
779 break;
780
781 /* skip uninteresting payload markers */
782 default:
783 if (get_word_be(&jpeg_buffer, &word))
784 break;
785 length = (long)word - 2;
786 skip(&jpeg_buffer, length);
787 break;
788 }
789 }
790 result->w = width;
791 result->h = height;
792 result->size = components;
f8433962
JA
793
794 switch (subsampling) {
795 case 0x11:
796 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444;
797 break;
798 case 0x21:
799 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422;
800 break;
801 case 0x22:
802 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420;
803 break;
804 case 0x33:
805 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
806 break;
807 default:
808 return false;
809 }
810
bb677f3a
AP
811 return !notfound;
812}
813
814static int s5p_jpeg_querycap(struct file *file, void *priv,
815 struct v4l2_capability *cap)
816{
275de24d 817 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
bb677f3a
AP
818
819 if (ctx->mode == S5P_JPEG_ENCODE) {
820 strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder",
821 sizeof(cap->driver));
822 strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
823 sizeof(cap->card));
824 } else {
825 strlcpy(cap->driver, S5P_JPEG_M2M_NAME " decoder",
826 sizeof(cap->driver));
827 strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
828 sizeof(cap->card));
829 }
830 cap->bus_info[0] = 0;
f0476a83
SN
831 /*
832 * This is only a mem-to-mem video device. The capture and output
833 * device capability flags are left only for backward compatibility
834 * and are scheduled for removal.
835 */
836 cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M |
837 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
bb677f3a
AP
838 return 0;
839}
840
80529ae5 841static int enum_fmt(struct s5p_jpeg_fmt *sjpeg_formats, int n,
bb677f3a
AP
842 struct v4l2_fmtdesc *f, u32 type)
843{
844 int i, num = 0;
845
846 for (i = 0; i < n; ++i) {
80529ae5 847 if (sjpeg_formats[i].flags & type) {
bb677f3a
AP
848 /* index-th format of type type found ? */
849 if (num == f->index)
850 break;
851 /* Correct type but haven't reached our index yet,
852 * just increment per-type index */
853 ++num;
854 }
855 }
856
857 /* Format not found */
858 if (i >= n)
859 return -EINVAL;
860
80529ae5
JA
861 strlcpy(f->description, sjpeg_formats[i].name, sizeof(f->description));
862 f->pixelformat = sjpeg_formats[i].fourcc;
bb677f3a
AP
863
864 return 0;
865}
866
867static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
868 struct v4l2_fmtdesc *f)
869{
275de24d 870 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
bb677f3a
AP
871
872 if (ctx->mode == S5P_JPEG_ENCODE)
80529ae5
JA
873 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
874 SJPEG_FMT_FLAG_ENC_CAPTURE);
bb677f3a 875
80529ae5
JA
876 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
877 SJPEG_FMT_FLAG_DEC_CAPTURE);
bb677f3a
AP
878}
879
880static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
881 struct v4l2_fmtdesc *f)
882{
275de24d 883 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
bb677f3a
AP
884
885 if (ctx->mode == S5P_JPEG_ENCODE)
80529ae5
JA
886 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
887 SJPEG_FMT_FLAG_ENC_OUTPUT);
bb677f3a 888
80529ae5
JA
889 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
890 SJPEG_FMT_FLAG_DEC_OUTPUT);
bb677f3a
AP
891}
892
893static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
894 enum v4l2_buf_type type)
895{
896 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
897 return &ctx->out_q;
898 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
899 return &ctx->cap_q;
900
901 return NULL;
902}
903
904static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
905{
906 struct vb2_queue *vq;
907 struct s5p_jpeg_q_data *q_data = NULL;
908 struct v4l2_pix_format *pix = &f->fmt.pix;
275de24d 909 struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);
bb677f3a 910
718cf4a9 911 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
bb677f3a
AP
912 if (!vq)
913 return -EINVAL;
914
915 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
916 ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
917 return -EINVAL;
918 q_data = get_q_data(ct, f->type);
919 BUG_ON(q_data == NULL);
920
921 pix->width = q_data->w;
922 pix->height = q_data->h;
923 pix->field = V4L2_FIELD_NONE;
924 pix->pixelformat = q_data->fmt->fourcc;
925 pix->bytesperline = 0;
926 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
927 u32 bpl = q_data->w;
928 if (q_data->fmt->colplanes == 1)
929 bpl = (bpl * q_data->fmt->depth) >> 3;
930 pix->bytesperline = bpl;
931 }
932 pix->sizeimage = q_data->size;
933
934 return 0;
935}
936
80529ae5
JA
937static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
938 u32 pixelformat, unsigned int fmt_type)
bb677f3a 939{
80529ae5 940 unsigned int k, fmt_flag, ver_flag;
bb677f3a 941
80529ae5
JA
942 if (ctx->mode == S5P_JPEG_ENCODE)
943 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
944 SJPEG_FMT_FLAG_ENC_OUTPUT :
945 SJPEG_FMT_FLAG_ENC_CAPTURE;
946 else
947 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
948 SJPEG_FMT_FLAG_DEC_OUTPUT :
949 SJPEG_FMT_FLAG_DEC_CAPTURE;
bb677f3a 950
80529ae5
JA
951 if (ctx->jpeg->variant->version == SJPEG_S5P)
952 ver_flag = SJPEG_FMT_FLAG_S5P;
953 else
954 ver_flag = SJPEG_FMT_FLAG_EXYNOS4;
955
956 for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) {
957 struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k];
958 if (fmt->fourcc == pixelformat &&
959 fmt->flags & fmt_flag &&
960 fmt->flags & ver_flag) {
bb677f3a 961 return fmt;
80529ae5 962 }
bb677f3a
AP
963 }
964
965 return NULL;
bb677f3a
AP
966}
967
968static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
969 unsigned int walign,
970 u32 *h, unsigned int hmin, unsigned int hmax,
971 unsigned int halign)
972{
973 int width, height, w_step, h_step;
974
975 width = *w;
976 height = *h;
977
978 w_step = 1 << walign;
979 h_step = 1 << halign;
980 v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
981
982 if (*w < width && (*w + w_step) < wmax)
983 *w += w_step;
984 if (*h < height && (*h + h_step) < hmax)
985 *h += h_step;
986
987}
988
989static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
990 struct s5p_jpeg_ctx *ctx, int q_type)
991{
992 struct v4l2_pix_format *pix = &f->fmt.pix;
993
994 if (pix->field == V4L2_FIELD_ANY)
995 pix->field = V4L2_FIELD_NONE;
996 else if (pix->field != V4L2_FIELD_NONE)
997 return -EINVAL;
998
999 /* V4L2 specification suggests the driver corrects the format struct
1000 * if any of the dimensions is unsupported */
80529ae5 1001 if (q_type == FMT_TYPE_OUTPUT)
bb677f3a
AP
1002 jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
1003 S5P_JPEG_MAX_WIDTH, 0,
1004 &pix->height, S5P_JPEG_MIN_HEIGHT,
1005 S5P_JPEG_MAX_HEIGHT, 0);
1006 else
1007 jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
1008 S5P_JPEG_MAX_WIDTH, fmt->h_align,
1009 &pix->height, S5P_JPEG_MIN_HEIGHT,
1010 S5P_JPEG_MAX_HEIGHT, fmt->v_align);
1011
1012 if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
1013 if (pix->sizeimage <= 0)
1014 pix->sizeimage = PAGE_SIZE;
1015 pix->bytesperline = 0;
1016 } else {
1017 u32 bpl = pix->bytesperline;
1018
1019 if (fmt->colplanes > 1 && bpl < pix->width)
1020 bpl = pix->width; /* planar */
1021
1022 if (fmt->colplanes == 1 && /* packed */
cc690904 1023 (bpl << 3) / fmt->depth < pix->width)
bb677f3a
AP
1024 bpl = (pix->width * fmt->depth) >> 3;
1025
1026 pix->bytesperline = bpl;
1027 pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
1028 }
1029
1030 return 0;
1031}
1032
1033static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
1034 struct v4l2_format *f)
1035{
275de24d 1036 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
337777a4 1037 struct v4l2_pix_format *pix = &f->fmt.pix;
bb677f3a 1038 struct s5p_jpeg_fmt *fmt;
337777a4 1039 int ret;
bb677f3a 1040
80529ae5
JA
1041 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1042 FMT_TYPE_CAPTURE);
1043 if (!fmt) {
bb677f3a
AP
1044 v4l2_err(&ctx->jpeg->v4l2_dev,
1045 "Fourcc format (0x%08x) invalid.\n",
1046 f->fmt.pix.pixelformat);
1047 return -EINVAL;
1048 }
1049
337777a4
JA
1050 /*
1051 * The exynos4x12 device requires resulting YUV image
1052 * subsampling not to be lower than the input jpeg subsampling.
1053 * If this requirement is not met then downgrade the requested
1054 * capture format to the one with subsampling equal to the input jpeg.
1055 */
1056 if ((ctx->jpeg->variant->version != SJPEG_S5P) &&
1057 (ctx->mode == S5P_JPEG_DECODE) &&
1058 (fmt->flags & SJPEG_FMT_NON_RGB) &&
1059 (fmt->subsampling < ctx->subsampling)) {
1060 ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
1061 fmt->fourcc,
1062 &pix->pixelformat,
1063 ctx);
1064 if (ret < 0)
1065 pix->pixelformat = V4L2_PIX_FMT_GREY;
1066
1067 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1068 FMT_TYPE_CAPTURE);
1069 }
1070
80529ae5 1071 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
bb677f3a
AP
1072}
1073
1074static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
1075 struct v4l2_format *f)
1076{
275de24d 1077 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
bb677f3a 1078 struct s5p_jpeg_fmt *fmt;
bb677f3a 1079
80529ae5
JA
1080 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1081 FMT_TYPE_OUTPUT);
1082 if (!fmt) {
bb677f3a
AP
1083 v4l2_err(&ctx->jpeg->v4l2_dev,
1084 "Fourcc format (0x%08x) invalid.\n",
1085 f->fmt.pix.pixelformat);
1086 return -EINVAL;
1087 }
1088
80529ae5 1089 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);
bb677f3a
AP
1090}
1091
1092static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
1093{
1094 struct vb2_queue *vq;
1095 struct s5p_jpeg_q_data *q_data = NULL;
1096 struct v4l2_pix_format *pix = &f->fmt.pix;
80529ae5 1097 unsigned int f_type;
bb677f3a 1098
718cf4a9 1099 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
bb677f3a
AP
1100 if (!vq)
1101 return -EINVAL;
1102
1103 q_data = get_q_data(ct, f->type);
1104 BUG_ON(q_data == NULL);
1105
1106 if (vb2_is_busy(vq)) {
1107 v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
1108 return -EBUSY;
1109 }
1110
80529ae5
JA
1111 f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
1112 FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;
1113
1114 q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);
bb677f3a
AP
1115 q_data->w = pix->width;
1116 q_data->h = pix->height;
1117 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG)
1118 q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
1119 else
1120 q_data->size = pix->sizeimage;
1121
1122 return 0;
1123}
1124
1125static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
1126 struct v4l2_format *f)
1127{
1128 int ret;
1129
1130 ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
1131 if (ret)
1132 return ret;
1133
275de24d 1134 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
bb677f3a
AP
1135}
1136
1137static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
1138 struct v4l2_format *f)
1139{
1140 int ret;
1141
1142 ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
1143 if (ret)
1144 return ret;
1145
275de24d 1146 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
bb677f3a
AP
1147}
1148
9f3bd320 1149static int s5p_jpeg_g_selection(struct file *file, void *priv,
bb677f3a
AP
1150 struct v4l2_selection *s)
1151{
275de24d 1152 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
bb677f3a
AP
1153
1154 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
80529ae5
JA
1155 s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1156 ctx->jpeg->variant->version != SJPEG_S5P)
bb677f3a
AP
1157 return -EINVAL;
1158
1159 /* For JPEG blob active == default == bounds */
1160 switch (s->target) {
c1334823 1161 case V4L2_SEL_TGT_CROP:
bb677f3a
AP
1162 case V4L2_SEL_TGT_CROP_BOUNDS:
1163 case V4L2_SEL_TGT_CROP_DEFAULT:
c1334823 1164 case V4L2_SEL_TGT_COMPOSE:
bb677f3a
AP
1165 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1166 s->r.width = ctx->out_q.w;
1167 s->r.height = ctx->out_q.h;
1168 break;
1169 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1170 case V4L2_SEL_TGT_COMPOSE_PADDED:
1171 s->r.width = ctx->cap_q.w;
1172 s->r.height = ctx->cap_q.h;
1173 break;
1174 default:
1175 return -EINVAL;
1176 }
1177 s->r.left = 0;
1178 s->r.top = 0;
1179 return 0;
1180}
1181
15f4bc3b
SN
1182/*
1183 * V4L2 controls
1184 */
1185
1186static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
bb677f3a 1187{
15f4bc3b
SN
1188 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1189 struct s5p_jpeg *jpeg = ctx->jpeg;
1190 unsigned long flags;
bb677f3a 1191
15f4bc3b
SN
1192 switch (ctrl->id) {
1193 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1194 spin_lock_irqsave(&jpeg->slock, flags);
bb677f3a 1195
15f4bc3b
SN
1196 WARN_ON(ctx->subsampling > S5P_SUBSAMPLING_MODE_GRAY);
1197 if (ctx->subsampling > 2)
1198 ctrl->val = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
1199 else
1200 ctrl->val = ctx->subsampling;
1201 spin_unlock_irqrestore(&jpeg->slock, flags);
1202 break;
1203 }
bb677f3a
AP
1204
1205 return 0;
1206}
1207
15f4bc3b 1208static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
bb677f3a 1209{
15f4bc3b
SN
1210 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1211 unsigned long flags;
bb677f3a 1212
15f4bc3b 1213 spin_lock_irqsave(&ctx->jpeg->slock, flags);
bb677f3a 1214
15f4bc3b
SN
1215 switch (ctrl->id) {
1216 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
78e5a3ce 1217 ctx->compr_quality = ctrl->val;
15f4bc3b
SN
1218 break;
1219 case V4L2_CID_JPEG_RESTART_INTERVAL:
1220 ctx->restart_interval = ctrl->val;
1221 break;
1222 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1223 ctx->subsampling = ctrl->val;
1224 break;
1225 }
1226
1227 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1228 return 0;
1229}
1230
1231static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {
1232 .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl,
1233 .s_ctrl = s5p_jpeg_s_ctrl,
1234};
1235
1236static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)
1237{
1238 unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */
1239 struct v4l2_ctrl *ctrl;
088f8300 1240 int ret;
15f4bc3b
SN
1241
1242 v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
bb677f3a 1243
15f4bc3b
SN
1244 if (ctx->mode == S5P_JPEG_ENCODE) {
1245 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1246 V4L2_CID_JPEG_COMPRESSION_QUALITY,
78e5a3ce 1247 0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);
15f4bc3b
SN
1248
1249 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1250 V4L2_CID_JPEG_RESTART_INTERVAL,
1251 0, 3, 0xffff, 0);
fdf9e2bc
JA
1252 if (ctx->jpeg->variant->version == SJPEG_S5P)
1253 mask = ~0x06; /* 422, 420 */
15f4bc3b
SN
1254 }
1255
1256 ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1257 V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
1258 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,
1259 V4L2_JPEG_CHROMA_SUBSAMPLING_422);
bb677f3a 1260
088f8300
JA
1261 if (ctx->ctrl_handler.error) {
1262 ret = ctx->ctrl_handler.error;
1263 goto error_free;
1264 }
15f4bc3b
SN
1265
1266 if (ctx->mode == S5P_JPEG_DECODE)
1267 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |
1268 V4L2_CTRL_FLAG_READ_ONLY;
088f8300
JA
1269
1270 ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
1271 if (ret < 0)
1272 goto error_free;
1273
1274 return ret;
1275
1276error_free:
1277 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1278 return ret;
bb677f3a
AP
1279}
1280
1281static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
1282 .vidioc_querycap = s5p_jpeg_querycap,
1283
1284 .vidioc_enum_fmt_vid_cap = s5p_jpeg_enum_fmt_vid_cap,
1285 .vidioc_enum_fmt_vid_out = s5p_jpeg_enum_fmt_vid_out,
1286
1287 .vidioc_g_fmt_vid_cap = s5p_jpeg_g_fmt,
1288 .vidioc_g_fmt_vid_out = s5p_jpeg_g_fmt,
1289
1290 .vidioc_try_fmt_vid_cap = s5p_jpeg_try_fmt_vid_cap,
1291 .vidioc_try_fmt_vid_out = s5p_jpeg_try_fmt_vid_out,
1292
1293 .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap,
1294 .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out,
1295
718cf4a9
SN
1296 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1297 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1298 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1299 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
bb677f3a 1300
718cf4a9
SN
1301 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
1302 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
bb677f3a
AP
1303
1304 .vidioc_g_selection = s5p_jpeg_g_selection,
bb677f3a
AP
1305};
1306
1307/*
1308 * ============================================================================
1309 * mem2mem callbacks
1310 * ============================================================================
1311 */
1312
1313static void s5p_jpeg_device_run(void *priv)
1314{
1315 struct s5p_jpeg_ctx *ctx = priv;
1316 struct s5p_jpeg *jpeg = ctx->jpeg;
1317 struct vb2_buffer *src_buf, *dst_buf;
b3c932a9
JA
1318 unsigned long src_addr, dst_addr, flags;
1319
1320 spin_lock_irqsave(&ctx->jpeg->slock, flags);
bb677f3a 1321
718cf4a9
SN
1322 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1323 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
bb677f3a
AP
1324 src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
1325 dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
1326
9f7b62d9
JA
1327 s5p_jpeg_reset(jpeg->regs);
1328 s5p_jpeg_poweron(jpeg->regs);
1329 s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);
bb677f3a
AP
1330 if (ctx->mode == S5P_JPEG_ENCODE) {
1331 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
9f7b62d9
JA
1332 s5p_jpeg_input_raw_mode(jpeg->regs,
1333 S5P_JPEG_RAW_IN_565);
bb677f3a 1334 else
9f7b62d9
JA
1335 s5p_jpeg_input_raw_mode(jpeg->regs,
1336 S5P_JPEG_RAW_IN_422);
1337 s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
1338 s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);
1339 s5p_jpeg_x(jpeg->regs, ctx->out_q.w);
1340 s5p_jpeg_y(jpeg->regs, ctx->out_q.h);
1341 s5p_jpeg_imgadr(jpeg->regs, src_addr);
1342 s5p_jpeg_jpgadr(jpeg->regs, dst_addr);
bb677f3a
AP
1343
1344 /* ultimately comes from sizeimage from userspace */
9f7b62d9 1345 s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
bb677f3a
AP
1346
1347 /* JPEG RGB to YCbCr conversion matrix */
9f7b62d9
JA
1348 s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
1349 s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
1350 s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
1351 s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
1352 s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
1353 s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
1354 s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
1355 s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
1356 s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
bb677f3a
AP
1357
1358 /*
1359 * JPEG IP allows storing 4 quantization tables
1360 * We fill table 0 for luma and table 1 for chroma
1361 */
31dc0ac0
JA
1362 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1363 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
bb677f3a 1364 /* use table 0 for Y */
9f7b62d9 1365 s5p_jpeg_qtbl(jpeg->regs, 1, 0);
bb677f3a 1366 /* use table 1 for Cb and Cr*/
9f7b62d9
JA
1367 s5p_jpeg_qtbl(jpeg->regs, 2, 1);
1368 s5p_jpeg_qtbl(jpeg->regs, 3, 1);
bb677f3a
AP
1369
1370 /* Y, Cb, Cr use Huffman table 0 */
9f7b62d9
JA
1371 s5p_jpeg_htbl_ac(jpeg->regs, 1);
1372 s5p_jpeg_htbl_dc(jpeg->regs, 1);
1373 s5p_jpeg_htbl_ac(jpeg->regs, 2);
1374 s5p_jpeg_htbl_dc(jpeg->regs, 2);
1375 s5p_jpeg_htbl_ac(jpeg->regs, 3);
1376 s5p_jpeg_htbl_dc(jpeg->regs, 3);
fb6f8c02 1377 } else { /* S5P_JPEG_DECODE */
9f7b62d9
JA
1378 s5p_jpeg_rst_int_enable(jpeg->regs, true);
1379 s5p_jpeg_data_num_int_enable(jpeg->regs, true);
1380 s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);
fb6f8c02 1381 if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
9f7b62d9 1382 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
fb6f8c02 1383 else
9f7b62d9
JA
1384 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
1385 s5p_jpeg_jpgadr(jpeg->regs, src_addr);
1386 s5p_jpeg_imgadr(jpeg->regs, dst_addr);
bb677f3a 1387 }
15f4bc3b 1388
9f7b62d9 1389 s5p_jpeg_start(jpeg->regs);
b3c932a9
JA
1390
1391 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
bb677f3a
AP
1392}
1393
80529ae5
JA
1394static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
1395{
1396 struct s5p_jpeg *jpeg = ctx->jpeg;
1397 struct s5p_jpeg_fmt *fmt;
1398 struct vb2_buffer *vb;
1399 struct s5p_jpeg_addr jpeg_addr;
1400 u32 pix_size, padding_bytes = 0;
1401
1402 pix_size = ctx->cap_q.w * ctx->cap_q.h;
1403
1404 if (ctx->mode == S5P_JPEG_ENCODE) {
1405 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1406 fmt = ctx->out_q.fmt;
1407 if (ctx->out_q.w % 2 && fmt->h_align > 0)
1408 padding_bytes = ctx->out_q.h;
1409 } else {
1410 fmt = ctx->cap_q.fmt;
1411 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1412 }
1413
1414 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
1415
1416 if (fmt->colplanes == 2) {
1417 jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;
1418 } else if (fmt->colplanes == 3) {
1419 jpeg_addr.cb = jpeg_addr.y + pix_size;
1420 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
1421 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
1422 else
1423 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
1424 }
1425
1426 exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);
1427}
1428
1429static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
1430{
1431 struct s5p_jpeg *jpeg = ctx->jpeg;
1432 struct vb2_buffer *vb;
1433 unsigned int jpeg_addr = 0;
1434
1435 if (ctx->mode == S5P_JPEG_ENCODE)
1436 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1437 else
1438 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1439
1440 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1441 exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
1442}
1443
1444static void exynos4_jpeg_device_run(void *priv)
1445{
1446 struct s5p_jpeg_ctx *ctx = priv;
1447 struct s5p_jpeg *jpeg = ctx->jpeg;
1448 unsigned int bitstream_size;
1449 unsigned long flags;
1450
1451 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1452
1453 if (ctx->mode == S5P_JPEG_ENCODE) {
1454 exynos4_jpeg_sw_reset(jpeg->regs);
1455 exynos4_jpeg_set_interrupt(jpeg->regs);
1456 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
1457
1458 exynos4_jpeg_set_huff_tbl(jpeg->regs);
1459
1460 /*
1461 * JPEG IP allows storing 4 quantization tables
1462 * We fill table 0 for luma and table 1 for chroma
1463 */
1464 exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1465 exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
1466
1467 exynos4_jpeg_set_encode_tbl_select(jpeg->regs,
1468 ctx->compr_quality);
1469 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
1470 ctx->cap_q.h);
1471
1472 exynos4_jpeg_set_enc_out_fmt(jpeg->regs, ctx->subsampling);
1473 exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->out_q.fmt->fourcc);
1474 exynos4_jpeg_set_img_addr(ctx);
1475 exynos4_jpeg_set_jpeg_addr(ctx);
1476 exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
1477 ctx->out_q.fmt->fourcc);
1478 } else {
1479 exynos4_jpeg_sw_reset(jpeg->regs);
1480 exynos4_jpeg_set_interrupt(jpeg->regs);
1481 exynos4_jpeg_set_img_addr(ctx);
1482 exynos4_jpeg_set_jpeg_addr(ctx);
1483 exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->cap_q.fmt->fourcc);
1484
1485 bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
1486
1487 exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
1488 }
1489
1490 exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
1491
1492 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1493}
1494
bb677f3a
AP
1495static int s5p_jpeg_job_ready(void *priv)
1496{
1497 struct s5p_jpeg_ctx *ctx = priv;
1498
1499 if (ctx->mode == S5P_JPEG_DECODE)
1500 return ctx->hdr_parsed;
1501 return 1;
1502}
1503
1504static void s5p_jpeg_job_abort(void *priv)
1505{
1506}
1507
1508static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
1509 .device_run = s5p_jpeg_device_run,
1510 .job_ready = s5p_jpeg_job_ready,
1511 .job_abort = s5p_jpeg_job_abort,
80529ae5
JA
1512}
1513;
1514static struct v4l2_m2m_ops exynos_jpeg_m2m_ops = {
1515 .device_run = exynos4_jpeg_device_run,
1516 .job_ready = s5p_jpeg_job_ready,
1517 .job_abort = s5p_jpeg_job_abort,
bb677f3a
AP
1518};
1519
1520/*
1521 * ============================================================================
1522 * Queue operations
1523 * ============================================================================
1524 */
1525
719c174e
MS
1526static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
1527 const struct v4l2_format *fmt,
1528 unsigned int *nbuffers, unsigned int *nplanes,
1529 unsigned int sizes[], void *alloc_ctxs[])
bb677f3a
AP
1530{
1531 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
1532 struct s5p_jpeg_q_data *q_data = NULL;
1533 unsigned int size, count = *nbuffers;
1534
1535 q_data = get_q_data(ctx, vq->type);
1536 BUG_ON(q_data == NULL);
1537
1538 size = q_data->size;
1539
1540 /*
1541 * header is parsed during decoding and parsed information stored
1542 * in the context so we do not allow another buffer to overwrite it
1543 */
1544 if (ctx->mode == S5P_JPEG_DECODE)
1545 count = 1;
1546
1547 *nbuffers = count;
1548 *nplanes = 1;
1549 sizes[0] = size;
1550 alloc_ctxs[0] = ctx->jpeg->alloc_ctx;
1551
1552 return 0;
1553}
1554
1555static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
1556{
1557 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1558 struct s5p_jpeg_q_data *q_data = NULL;
1559
1560 q_data = get_q_data(ctx, vb->vb2_queue->type);
1561 BUG_ON(q_data == NULL);
1562
1563 if (vb2_plane_size(vb, 0) < q_data->size) {
1564 pr_err("%s data will not fit into plane (%lu < %lu)\n",
1565 __func__, vb2_plane_size(vb, 0),
1566 (long)q_data->size);
1567 return -EINVAL;
1568 }
1569
1570 vb2_set_plane_payload(vb, 0, q_data->size);
1571
1572 return 0;
1573}
1574
1575static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
1576{
1577 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1578
1579 if (ctx->mode == S5P_JPEG_DECODE &&
1580 vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1581 struct s5p_jpeg_q_data tmp, *q_data;
1582 ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
1583 (unsigned long)vb2_plane_vaddr(vb, 0),
1584 min((unsigned long)ctx->out_q.size,
f8433962 1585 vb2_get_plane_payload(vb, 0)), ctx);
bb677f3a
AP
1586 if (!ctx->hdr_parsed) {
1587 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
1588 return;
1589 }
1590
1591 q_data = &ctx->out_q;
1592 q_data->w = tmp.w;
1593 q_data->h = tmp.h;
1594
1595 q_data = &ctx->cap_q;
1596 q_data->w = tmp.w;
1597 q_data->h = tmp.h;
bb677f3a 1598 }
bb677f3a 1599
718cf4a9 1600 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
bb677f3a
AP
1601}
1602
1603static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
1604{
1605 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
1606 int ret;
1607
1608 ret = pm_runtime_get_sync(ctx->jpeg->dev);
1609
1610 return ret > 0 ? 0 : ret;
1611}
1612
1613static int s5p_jpeg_stop_streaming(struct vb2_queue *q)
1614{
1615 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
1616
1617 pm_runtime_put(ctx->jpeg->dev);
1618
1619 return 0;
1620}
1621
1622static struct vb2_ops s5p_jpeg_qops = {
1623 .queue_setup = s5p_jpeg_queue_setup,
1624 .buf_prepare = s5p_jpeg_buf_prepare,
1625 .buf_queue = s5p_jpeg_buf_queue,
718cf4a9
SN
1626 .wait_prepare = vb2_ops_wait_prepare,
1627 .wait_finish = vb2_ops_wait_finish,
bb677f3a
AP
1628 .start_streaming = s5p_jpeg_start_streaming,
1629 .stop_streaming = s5p_jpeg_stop_streaming,
1630};
1631
1632static int queue_init(void *priv, struct vb2_queue *src_vq,
1633 struct vb2_queue *dst_vq)
1634{
1635 struct s5p_jpeg_ctx *ctx = priv;
1636 int ret;
1637
bb677f3a
AP
1638 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1639 src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
1640 src_vq->drv_priv = ctx;
1641 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1642 src_vq->ops = &s5p_jpeg_qops;
1643 src_vq->mem_ops = &vb2_dma_contig_memops;
aca326ae 1644 src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
718cf4a9 1645 src_vq->lock = &ctx->jpeg->lock;
bb677f3a
AP
1646
1647 ret = vb2_queue_init(src_vq);
1648 if (ret)
1649 return ret;
1650
bb677f3a
AP
1651 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1652 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
1653 dst_vq->drv_priv = ctx;
1654 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1655 dst_vq->ops = &s5p_jpeg_qops;
1656 dst_vq->mem_ops = &vb2_dma_contig_memops;
aca326ae 1657 dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
718cf4a9 1658 dst_vq->lock = &ctx->jpeg->lock;
bb677f3a
AP
1659
1660 return vb2_queue_init(dst_vq);
1661}
1662
1663/*
1664 * ============================================================================
1665 * ISR
1666 * ============================================================================
1667 */
1668
1669static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
1670{
1671 struct s5p_jpeg *jpeg = dev_id;
1672 struct s5p_jpeg_ctx *curr_ctx;
1673 struct vb2_buffer *src_buf, *dst_buf;
1674 unsigned long payload_size = 0;
1675 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
1676 bool enc_jpeg_too_large = false;
1677 bool timer_elapsed = false;
1678 bool op_completed = false;
1679
15f4bc3b
SN
1680 spin_lock(&jpeg->slock);
1681
bb677f3a
AP
1682 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
1683
718cf4a9
SN
1684 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
1685 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
bb677f3a
AP
1686
1687 if (curr_ctx->mode == S5P_JPEG_ENCODE)
9f7b62d9
JA
1688 enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);
1689 timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);
1690 op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);
bb677f3a 1691 if (curr_ctx->mode == S5P_JPEG_DECODE)
9f7b62d9
JA
1692 op_completed = op_completed &&
1693 s5p_jpeg_stream_stat_ok(jpeg->regs);
bb677f3a
AP
1694
1695 if (enc_jpeg_too_large) {
1696 state = VB2_BUF_STATE_ERROR;
9f7b62d9 1697 s5p_jpeg_clear_enc_stream_stat(jpeg->regs);
bb677f3a
AP
1698 } else if (timer_elapsed) {
1699 state = VB2_BUF_STATE_ERROR;
9f7b62d9 1700 s5p_jpeg_clear_timer_stat(jpeg->regs);
bb677f3a
AP
1701 } else if (!op_completed) {
1702 state = VB2_BUF_STATE_ERROR;
1703 } else {
9f7b62d9 1704 payload_size = s5p_jpeg_compressed_size(jpeg->regs);
bb677f3a
AP
1705 }
1706
aca326ae
KD
1707 dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
1708 dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
1709
bb677f3a
AP
1710 v4l2_m2m_buf_done(src_buf, state);
1711 if (curr_ctx->mode == S5P_JPEG_ENCODE)
1712 vb2_set_plane_payload(dst_buf, 0, payload_size);
1713 v4l2_m2m_buf_done(dst_buf, state);
718cf4a9 1714 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
bb677f3a 1715
9f7b62d9 1716 curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);
15f4bc3b 1717 spin_unlock(&jpeg->slock);
fb6f8c02 1718
9f7b62d9 1719 s5p_jpeg_clear_int(jpeg->regs);
bb677f3a
AP
1720
1721 return IRQ_HANDLED;
1722}
1723
80529ae5
JA
1724static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
1725{
1726 unsigned int int_status;
1727 struct vb2_buffer *src_vb, *dst_vb;
1728 struct s5p_jpeg *jpeg = priv;
1729 struct s5p_jpeg_ctx *curr_ctx;
1730 unsigned long payload_size = 0;
1731
1732 spin_lock(&jpeg->slock);
1733
1734 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
1735
1736 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
1737 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
1738
1739 int_status = exynos4_jpeg_get_int_status(jpeg->regs);
1740
1741 if (int_status) {
1742 switch (int_status & 0x1f) {
1743 case 0x1:
1744 jpeg->irq_ret = ERR_PROT;
1745 break;
1746 case 0x2:
1747 jpeg->irq_ret = OK_ENC_OR_DEC;
1748 break;
1749 case 0x4:
1750 jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;
1751 break;
1752 case 0x8:
1753 jpeg->irq_ret = ERR_MULTI_SCAN;
1754 break;
1755 case 0x10:
1756 jpeg->irq_ret = ERR_FRAME;
1757 break;
1758 default:
1759 jpeg->irq_ret = ERR_UNKNOWN;
1760 break;
1761 }
1762 } else {
1763 jpeg->irq_ret = ERR_UNKNOWN;
1764 }
1765
1766 if (jpeg->irq_ret == OK_ENC_OR_DEC) {
1767 if (curr_ctx->mode == S5P_JPEG_ENCODE) {
1768 payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
1769 vb2_set_plane_payload(dst_vb, 0, payload_size);
1770 }
1771 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
1772 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
1773 } else {
1774 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
1775 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
1776 }
1777
1778 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
1779 curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
1780
1781 spin_unlock(&jpeg->slock);
1782 return IRQ_HANDLED;
1783}
1784
1785static void *jpeg_get_drv_data(struct platform_device *pdev);
1786
bb677f3a
AP
1787/*
1788 * ============================================================================
1789 * Driver basic infrastructure
1790 * ============================================================================
1791 */
1792
1793static int s5p_jpeg_probe(struct platform_device *pdev)
1794{
1795 struct s5p_jpeg *jpeg;
1796 struct resource *res;
80529ae5 1797 struct v4l2_m2m_ops *samsung_jpeg_m2m_ops;
bb677f3a
AP
1798 int ret;
1799
80529ae5
JA
1800 if (!pdev->dev.of_node)
1801 return -ENODEV;
1802
bb677f3a 1803 /* JPEG IP abstraction struct */
5b58b954 1804 jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
bb677f3a
AP
1805 if (!jpeg)
1806 return -ENOMEM;
1807
80529ae5
JA
1808 jpeg->variant = jpeg_get_drv_data(pdev);
1809
bb677f3a 1810 mutex_init(&jpeg->lock);
15f4bc3b 1811 spin_lock_init(&jpeg->slock);
bb677f3a
AP
1812 jpeg->dev = &pdev->dev;
1813
1814 /* memory-mapped registers */
1815 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bb677f3a 1816
f23999ec
TR
1817 jpeg->regs = devm_ioremap_resource(&pdev->dev, res);
1818 if (IS_ERR(jpeg->regs))
1819 return PTR_ERR(jpeg->regs);
bb677f3a 1820
bb677f3a
AP
1821 /* interrupt service routine registration */
1822 jpeg->irq = ret = platform_get_irq(pdev, 0);
1823 if (ret < 0) {
1824 dev_err(&pdev->dev, "cannot find IRQ\n");
5b58b954 1825 return ret;
bb677f3a
AP
1826 }
1827
80529ae5
JA
1828 ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,
1829 0, dev_name(&pdev->dev), jpeg);
bb677f3a
AP
1830 if (ret) {
1831 dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
5b58b954 1832 return ret;
bb677f3a
AP
1833 }
1834
1835 /* clocks */
1836 jpeg->clk = clk_get(&pdev->dev, "jpeg");
1837 if (IS_ERR(jpeg->clk)) {
1838 dev_err(&pdev->dev, "cannot get clock\n");
1839 ret = PTR_ERR(jpeg->clk);
5b58b954 1840 return ret;
bb677f3a
AP
1841 }
1842 dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
bb677f3a
AP
1843
1844 /* v4l2 device */
1845 ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
1846 if (ret) {
1847 dev_err(&pdev->dev, "Failed to register v4l2 device\n");
1848 goto clk_get_rollback;
1849 }
1850
80529ae5
JA
1851 if (jpeg->variant->version == SJPEG_S5P)
1852 samsung_jpeg_m2m_ops = &s5p_jpeg_m2m_ops;
1853 else
1854 samsung_jpeg_m2m_ops = &exynos_jpeg_m2m_ops;
1855
bb677f3a 1856 /* mem2mem device */
80529ae5 1857 jpeg->m2m_dev = v4l2_m2m_init(samsung_jpeg_m2m_ops);
bb677f3a
AP
1858 if (IS_ERR(jpeg->m2m_dev)) {
1859 v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
1860 ret = PTR_ERR(jpeg->m2m_dev);
1861 goto device_register_rollback;
1862 }
1863
1864 jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1865 if (IS_ERR(jpeg->alloc_ctx)) {
1866 v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
1867 ret = PTR_ERR(jpeg->alloc_ctx);
1868 goto m2m_init_rollback;
1869 }
1870
1871 /* JPEG encoder /dev/videoX node */
1872 jpeg->vfd_encoder = video_device_alloc();
1873 if (!jpeg->vfd_encoder) {
1874 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
1875 ret = -ENOMEM;
1876 goto vb2_allocator_rollback;
1877 }
baaf046d
SWK
1878 snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),
1879 "%s-enc", S5P_JPEG_M2M_NAME);
bb677f3a
AP
1880 jpeg->vfd_encoder->fops = &s5p_jpeg_fops;
1881 jpeg->vfd_encoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
1882 jpeg->vfd_encoder->minor = -1;
1883 jpeg->vfd_encoder->release = video_device_release;
1884 jpeg->vfd_encoder->lock = &jpeg->lock;
1885 jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev;
954f340f 1886 jpeg->vfd_encoder->vfl_dir = VFL_DIR_M2M;
bb677f3a
AP
1887
1888 ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
1889 if (ret) {
1890 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
1891 goto enc_vdev_alloc_rollback;
1892 }
1893
1894 video_set_drvdata(jpeg->vfd_encoder, jpeg);
1895 v4l2_info(&jpeg->v4l2_dev,
1896 "encoder device registered as /dev/video%d\n",
1897 jpeg->vfd_encoder->num);
1898
1899 /* JPEG decoder /dev/videoX node */
1900 jpeg->vfd_decoder = video_device_alloc();
1901 if (!jpeg->vfd_decoder) {
1902 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
1903 ret = -ENOMEM;
1904 goto enc_vdev_register_rollback;
1905 }
baaf046d
SWK
1906 snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),
1907 "%s-dec", S5P_JPEG_M2M_NAME);
bb677f3a
AP
1908 jpeg->vfd_decoder->fops = &s5p_jpeg_fops;
1909 jpeg->vfd_decoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
1910 jpeg->vfd_decoder->minor = -1;
1911 jpeg->vfd_decoder->release = video_device_release;
1912 jpeg->vfd_decoder->lock = &jpeg->lock;
1913 jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev;
7f7d8fe2 1914 jpeg->vfd_decoder->vfl_dir = VFL_DIR_M2M;
bb677f3a
AP
1915
1916 ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
1917 if (ret) {
1918 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
1919 goto dec_vdev_alloc_rollback;
1920 }
1921
1922 video_set_drvdata(jpeg->vfd_decoder, jpeg);
1923 v4l2_info(&jpeg->v4l2_dev,
1924 "decoder device registered as /dev/video%d\n",
1925 jpeg->vfd_decoder->num);
1926
1927 /* final statements & power management */
1928 platform_set_drvdata(pdev, jpeg);
1929
1930 pm_runtime_enable(&pdev->dev);
1931
1932 v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
1933
1934 return 0;
1935
1936dec_vdev_alloc_rollback:
1937 video_device_release(jpeg->vfd_decoder);
1938
1939enc_vdev_register_rollback:
1940 video_unregister_device(jpeg->vfd_encoder);
1941
1942enc_vdev_alloc_rollback:
1943 video_device_release(jpeg->vfd_encoder);
1944
1945vb2_allocator_rollback:
1946 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
1947
1948m2m_init_rollback:
1949 v4l2_m2m_release(jpeg->m2m_dev);
1950
1951device_register_rollback:
1952 v4l2_device_unregister(&jpeg->v4l2_dev);
1953
1954clk_get_rollback:
bb677f3a
AP
1955 clk_put(jpeg->clk);
1956
bb677f3a
AP
1957 return ret;
1958}
1959
1960static int s5p_jpeg_remove(struct platform_device *pdev)
1961{
1962 struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
1963
1964 pm_runtime_disable(jpeg->dev);
1965
1966 video_unregister_device(jpeg->vfd_decoder);
1967 video_device_release(jpeg->vfd_decoder);
1968 video_unregister_device(jpeg->vfd_encoder);
1969 video_device_release(jpeg->vfd_encoder);
1970 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
1971 v4l2_m2m_release(jpeg->m2m_dev);
1972 v4l2_device_unregister(&jpeg->v4l2_dev);
1973
f1347132
JA
1974 if (!pm_runtime_status_suspended(&pdev->dev))
1975 clk_disable_unprepare(jpeg->clk);
1976
bb677f3a
AP
1977 clk_put(jpeg->clk);
1978
bb677f3a
AP
1979 return 0;
1980}
1981
1982static int s5p_jpeg_runtime_suspend(struct device *dev)
1983{
f1347132
JA
1984 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
1985
1986 clk_disable_unprepare(jpeg->clk);
1987
bb677f3a
AP
1988 return 0;
1989}
1990
1991static int s5p_jpeg_runtime_resume(struct device *dev)
1992{
1993 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
b3c932a9 1994 unsigned long flags;
f1347132
JA
1995 int ret;
1996
1997 ret = clk_prepare_enable(jpeg->clk);
1998 if (ret < 0)
1999 return ret;
31dc0ac0 2000
b3c932a9
JA
2001 spin_lock_irqsave(&jpeg->slock, flags);
2002
bb677f3a
AP
2003 /*
2004 * JPEG IP allows storing two Huffman tables for each component
80529ae5
JA
2005 * We fill table 0 for each component and do this here only
2006 * for S5PC210 device as Exynos4x12 requires programming its
2007 * Huffman tables each time the encoding process is initialized.
bb677f3a 2008 */
80529ae5
JA
2009 if (jpeg->variant->version == SJPEG_S5P) {
2010 s5p_jpeg_set_hdctbl(jpeg->regs);
2011 s5p_jpeg_set_hdctblg(jpeg->regs);
2012 s5p_jpeg_set_hactbl(jpeg->regs);
2013 s5p_jpeg_set_hactblg(jpeg->regs);
2014 }
31dc0ac0 2015
b3c932a9
JA
2016 spin_unlock_irqrestore(&jpeg->slock, flags);
2017
bb677f3a
AP
2018 return 0;
2019}
2020
f1347132
JA
2021static int s5p_jpeg_suspend(struct device *dev)
2022{
2023 if (pm_runtime_suspended(dev))
2024 return 0;
2025
2026 return s5p_jpeg_runtime_suspend(dev);
2027}
2028
2029static int s5p_jpeg_resume(struct device *dev)
2030{
2031 if (pm_runtime_suspended(dev))
2032 return 0;
2033
2034 return s5p_jpeg_runtime_resume(dev);
2035}
2036
bb677f3a 2037static const struct dev_pm_ops s5p_jpeg_pm_ops = {
f1347132
JA
2038 SET_SYSTEM_SLEEP_PM_OPS(s5p_jpeg_suspend, s5p_jpeg_resume)
2039 SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume, NULL)
bb677f3a
AP
2040};
2041
f7074ab3 2042#ifdef CONFIG_OF
80529ae5
JA
2043static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
2044 .version = SJPEG_S5P,
2045 .jpeg_irq = s5p_jpeg_irq,
f7074ab3 2046};
80529ae5
JA
2047
2048static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
2049 .version = SJPEG_EXYNOS4,
2050 .jpeg_irq = exynos4_jpeg_irq,
2051};
2052
2053static const struct of_device_id samsung_jpeg_match[] = {
2054 {
2055 .compatible = "samsung,s5pv210-jpeg",
2056 .data = &s5p_jpeg_drvdata,
2057 }, {
2058 .compatible = "samsung,exynos4210-jpeg",
2059 .data = &s5p_jpeg_drvdata,
2060 }, {
2061 .compatible = "samsung,exynos4212-jpeg",
2062 .data = &exynos4_jpeg_drvdata,
2063 },
2064 {},
2065};
2066
2067MODULE_DEVICE_TABLE(of, samsung_jpeg_match);
2068
2069static void *jpeg_get_drv_data(struct platform_device *pdev)
2070{
2071 struct s5p_jpeg_variant *driver_data = NULL;
2072 const struct of_device_id *match;
2073
2074 match = of_match_node(of_match_ptr(samsung_jpeg_match),
2075 pdev->dev.of_node);
2076 if (match)
2077 driver_data = (struct s5p_jpeg_variant *)match->data;
2078
2079 return driver_data;
2080}
f7074ab3
SN
2081#endif
2082
bb677f3a
AP
2083static struct platform_driver s5p_jpeg_driver = {
2084 .probe = s5p_jpeg_probe,
2085 .remove = s5p_jpeg_remove,
2086 .driver = {
80529ae5
JA
2087 .of_match_table = of_match_ptr(samsung_jpeg_match),
2088 .owner = THIS_MODULE,
2089 .name = S5P_JPEG_M2M_NAME,
2090 .pm = &s5p_jpeg_pm_ops,
bb677f3a
AP
2091 },
2092};
2093
87e94294 2094module_platform_driver(s5p_jpeg_driver);
bb677f3a
AP
2095
2096MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
80529ae5 2097MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
bb677f3a
AP
2098MODULE_DESCRIPTION("Samsung JPEG codec driver");
2099MODULE_LICENSE("GPL");
This page took 0.253611 seconds and 5 git commands to generate.