blob: 6da2c6220353ab6c09c4db83f9d91f500b205123 [file] [log] [blame]
Mauro Carvalho Chehab2c3fb082012-08-14 17:31:16 -03001/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002 *
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03003 * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd.
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03004 * http://www.samsung.com
5 *
6 * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03007 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03008 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/clk.h>
15#include <linux/err.h>
16#include <linux/gfp.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -030021#include <linux/of.h>
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030022#include <linux/platform_device.h>
23#include <linux/pm_runtime.h>
24#include <linux/slab.h>
25#include <linux/spinlock.h>
26#include <linux/string.h>
27#include <media/v4l2-mem2mem.h>
28#include <media/v4l2-ioctl.h>
29#include <media/videobuf2-core.h>
30#include <media/videobuf2-dma-contig.h>
31
32#include "jpeg-core.h"
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -030033#include "jpeg-hw-s5p.h"
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030034#include "jpeg-hw-exynos4.h"
35#include "jpeg-regs.h"
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030036
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030037static struct s5p_jpeg_fmt sjpeg_formats[] = {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030038 {
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -030039 .name = "JPEG JFIF",
40 .fourcc = V4L2_PIX_FMT_JPEG,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030041 .flags = SJPEG_FMT_FLAG_ENC_CAPTURE |
42 SJPEG_FMT_FLAG_DEC_OUTPUT |
43 SJPEG_FMT_FLAG_S5P |
44 SJPEG_FMT_FLAG_EXYNOS4,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030045 },
46 {
47 .name = "YUV 4:2:2 packed, YCbYCr",
48 .fourcc = V4L2_PIX_FMT_YUYV,
49 .depth = 16,
50 .colplanes = 1,
51 .h_align = 4,
52 .v_align = 3,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030053 .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,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030058 },
59 {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030060 .name = "YUV 4:2:2 packed, YCbYCr",
61 .fourcc = V4L2_PIX_FMT_YUYV,
62 .depth = 16,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030063 .colplanes = 1,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -030064 .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,
84 },
85 {
86 .name = "RGB565",
87 .fourcc = V4L2_PIX_FMT_RGB565,
88 .depth = 16,
89 .colplanes = 1,
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,
161 },
162 {
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",
177 .fourcc = V4L2_PIX_FMT_NV12,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300178 .depth = 12,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300179 .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,
187 },
188 {
189 .name = "YUV 4:2:0 planar, Y/CbCr",
190 .fourcc = V4L2_PIX_FMT_NV12,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300191 .depth = 12,
192 .colplanes = 2,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300193 .h_align = 4,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300194 .v_align = 4,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300195 .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,
200 },
201 {
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,
231 .colplanes = 1,
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,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300237 },
238};
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300239#define SJPEG_NUM_FORMATS ARRAY_SIZE(sjpeg_formats)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300240
241static const unsigned char qtbl_luminance[4][64] = {
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300242 {/*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
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300261 },
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 },
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300272 {/* 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
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300281 }
282};
283
284static const unsigned char qtbl_chrominance[4][64] = {
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300285 {/*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
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300304 },
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 },
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300315 {/* 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
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300324 }
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
Jacek Anaszewski337777a2013-11-22 06:13:34 -0300361/*
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
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300454static int exynos4x12_decoded_subsampling[] = {
455 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
456 V4L2_JPEG_CHROMA_SUBSAMPLING_444,
457 V4L2_JPEG_CHROMA_SUBSAMPLING_422,
458 V4L2_JPEG_CHROMA_SUBSAMPLING_420,
459};
460
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300461static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
462{
463 return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
464}
465
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300466static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh)
467{
468 return container_of(fh, struct s5p_jpeg_ctx, fh);
469}
470
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300471static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
472{
473 WARN_ON(ctx->subsampling > 3);
474
475 if (ctx->jpeg->variant->version == SJPEG_S5P) {
476 if (ctx->subsampling > 2)
477 return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
478 return ctx->subsampling;
479 } else {
480 if (ctx->subsampling > 2)
481 return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
482 return exynos4x12_decoded_subsampling[ctx->subsampling];
483 }
484}
485
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300486static inline void s5p_jpeg_set_qtbl(void __iomem *regs,
487 const unsigned char *qtbl,
488 unsigned long tab, int len)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300489{
490 int i;
491
492 for (i = 0; i < len; i++)
493 writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
494}
495
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300496static inline void s5p_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300497{
498 /* this driver fills quantisation table 0 with data for luma */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300499 s5p_jpeg_set_qtbl(regs, qtbl_luminance[quality],
500 S5P_JPG_QTBL_CONTENT(0),
501 ARRAY_SIZE(qtbl_luminance[quality]));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300502}
503
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300504static inline void s5p_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300505{
506 /* this driver fills quantisation table 1 with data for chroma */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300507 s5p_jpeg_set_qtbl(regs, qtbl_chrominance[quality],
508 S5P_JPG_QTBL_CONTENT(1),
509 ARRAY_SIZE(qtbl_chrominance[quality]));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300510}
511
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300512static inline void s5p_jpeg_set_htbl(void __iomem *regs,
513 const unsigned char *htbl,
514 unsigned long tab, int len)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300515{
516 int i;
517
518 for (i = 0; i < len; i++)
519 writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
520}
521
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300522static inline void s5p_jpeg_set_hdctbl(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300523{
524 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300525 s5p_jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0),
526 ARRAY_SIZE(hdctbl0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300527}
528
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300529static inline void s5p_jpeg_set_hdctblg(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300530{
531 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300532 s5p_jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0),
533 ARRAY_SIZE(hdctblg0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300534}
535
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300536static inline void s5p_jpeg_set_hactbl(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300537{
538 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300539 s5p_jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0),
540 ARRAY_SIZE(hactbl0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300541}
542
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300543static inline void s5p_jpeg_set_hactblg(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300544{
545 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300546 s5p_jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0),
547 ARRAY_SIZE(hactblg0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300548}
549
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300550static inline void exynos4_jpeg_set_tbl(void __iomem *regs,
551 const unsigned char *tbl,
552 unsigned long tab, int len)
553{
554 int i;
555 unsigned int dword;
556
557 for (i = 0; i < len; i += 4) {
558 dword = tbl[i] |
559 (tbl[i + 1] << 8) |
560 (tbl[i + 2] << 16) |
561 (tbl[i + 3] << 24);
562 writel(dword, regs + tab + i);
563 }
564}
565
566static inline void exynos4_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
567{
568 /* this driver fills quantisation table 0 with data for luma */
569 exynos4_jpeg_set_tbl(regs, qtbl_luminance[quality],
570 EXYNOS4_QTBL_CONTENT(0),
571 ARRAY_SIZE(qtbl_luminance[quality]));
572}
573
574static inline void exynos4_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
575{
576 /* this driver fills quantisation table 1 with data for chroma */
577 exynos4_jpeg_set_tbl(regs, qtbl_chrominance[quality],
578 EXYNOS4_QTBL_CONTENT(1),
579 ARRAY_SIZE(qtbl_chrominance[quality]));
580}
581
582void exynos4_jpeg_set_huff_tbl(void __iomem *base)
583{
584 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCLL,
585 ARRAY_SIZE(hdctbl0));
586 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCCL,
587 ARRAY_SIZE(hdctbl0));
588 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCLV,
589 ARRAY_SIZE(hdctblg0));
590 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCCV,
591 ARRAY_SIZE(hdctblg0));
592 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACLL,
593 ARRAY_SIZE(hactbl0));
594 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACCL,
595 ARRAY_SIZE(hactbl0));
596 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACLV,
597 ARRAY_SIZE(hactblg0));
598 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV,
599 ARRAY_SIZE(hactblg0));
600}
601
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300602/*
603 * ============================================================================
604 * Device file operations
605 * ============================================================================
606 */
607
608static int queue_init(void *priv, struct vb2_queue *src_vq,
609 struct vb2_queue *dst_vq);
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300610static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
611 __u32 pixelformat, unsigned int fmt_type);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300612static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300613
614static int s5p_jpeg_open(struct file *file)
615{
616 struct s5p_jpeg *jpeg = video_drvdata(file);
617 struct video_device *vfd = video_devdata(file);
618 struct s5p_jpeg_ctx *ctx;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300619 struct s5p_jpeg_fmt *out_fmt, *cap_fmt;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300620 int ret = 0;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300621
Sachin Kamatb5146c92012-08-16 08:52:58 -0300622 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300623 if (!ctx)
624 return -ENOMEM;
625
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300626 if (mutex_lock_interruptible(&jpeg->lock)) {
627 ret = -ERESTARTSYS;
628 goto free;
629 }
630
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300631 v4l2_fh_init(&ctx->fh, vfd);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300632 /* Use separate control handler per file handle */
633 ctx->fh.ctrl_handler = &ctx->ctrl_handler;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300634 file->private_data = &ctx->fh;
635 v4l2_fh_add(&ctx->fh);
636
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300637 ctx->jpeg = jpeg;
638 if (vfd == jpeg->vfd_encoder) {
639 ctx->mode = S5P_JPEG_ENCODE;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300640 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_RGB565,
641 FMT_TYPE_OUTPUT);
642 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
643 FMT_TYPE_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300644 } else {
645 ctx->mode = S5P_JPEG_DECODE;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300646 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
647 FMT_TYPE_OUTPUT);
648 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
649 FMT_TYPE_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300650 }
651
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300652 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
653 if (IS_ERR(ctx->fh.m2m_ctx)) {
654 ret = PTR_ERR(ctx->fh.m2m_ctx);
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300655 goto error;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300656 }
657
658 ctx->out_q.fmt = out_fmt;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300659 ctx->cap_q.fmt = cap_fmt;
660
661 ret = s5p_jpeg_controls_create(ctx);
662 if (ret < 0)
663 goto error;
664
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300665 mutex_unlock(&jpeg->lock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300666 return 0;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300667
668error:
669 v4l2_fh_del(&ctx->fh);
670 v4l2_fh_exit(&ctx->fh);
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300671 mutex_unlock(&jpeg->lock);
672free:
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300673 kfree(ctx);
674 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300675}
676
677static int s5p_jpeg_release(struct file *file)
678{
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300679 struct s5p_jpeg *jpeg = video_drvdata(file);
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300680 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300681
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300682 mutex_lock(&jpeg->lock);
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300683 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300684 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300685 v4l2_fh_del(&ctx->fh);
686 v4l2_fh_exit(&ctx->fh);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300687 kfree(ctx);
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300688 mutex_unlock(&jpeg->lock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300689
690 return 0;
691}
692
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300693static const struct v4l2_file_operations s5p_jpeg_fops = {
694 .owner = THIS_MODULE,
695 .open = s5p_jpeg_open,
696 .release = s5p_jpeg_release,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300697 .poll = v4l2_m2m_fop_poll,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300698 .unlocked_ioctl = video_ioctl2,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300699 .mmap = v4l2_m2m_fop_mmap,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300700};
701
702/*
703 * ============================================================================
704 * video ioctl operations
705 * ============================================================================
706 */
707
708static int get_byte(struct s5p_jpeg_buffer *buf)
709{
710 if (buf->curr >= buf->size)
711 return -1;
712
713 return ((unsigned char *)buf->data)[buf->curr++];
714}
715
716static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
717{
718 unsigned int temp;
719 int byte;
720
721 byte = get_byte(buf);
722 if (byte == -1)
723 return -1;
724 temp = byte << 8;
725 byte = get_byte(buf);
726 if (byte == -1)
727 return -1;
728 *word = (unsigned int)byte | temp;
729 return 0;
730}
731
732static void skip(struct s5p_jpeg_buffer *buf, long len)
733{
734 if (len <= 0)
735 return;
736
737 while (len--)
738 get_byte(buf);
739}
740
741static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
Jacek Anaszewskif8433962013-11-21 13:33:09 -0300742 unsigned long buffer, unsigned long size,
743 struct s5p_jpeg_ctx *ctx)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300744{
745 int c, components, notfound;
Jacek Anaszewskif8433962013-11-21 13:33:09 -0300746 unsigned int height, width, word, subsampling = 0;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300747 long length;
748 struct s5p_jpeg_buffer jpeg_buffer;
749
750 jpeg_buffer.size = size;
751 jpeg_buffer.data = buffer;
752 jpeg_buffer.curr = 0;
753
754 notfound = 1;
755 while (notfound) {
756 c = get_byte(&jpeg_buffer);
757 if (c == -1)
758 break;
759 if (c != 0xff)
760 continue;
761 do
762 c = get_byte(&jpeg_buffer);
763 while (c == 0xff);
764 if (c == -1)
765 break;
766 if (c == 0)
767 continue;
768 length = 0;
769 switch (c) {
770 /* SOF0: baseline JPEG */
771 case SOF0:
772 if (get_word_be(&jpeg_buffer, &word))
773 break;
774 if (get_byte(&jpeg_buffer) == -1)
775 break;
776 if (get_word_be(&jpeg_buffer, &height))
777 break;
778 if (get_word_be(&jpeg_buffer, &width))
779 break;
780 components = get_byte(&jpeg_buffer);
781 if (components == -1)
782 break;
783 notfound = 0;
784
Jacek Anaszewskif8433962013-11-21 13:33:09 -0300785 if (components == 1) {
786 subsampling = 0x33;
787 } else {
788 skip(&jpeg_buffer, 1);
789 subsampling = get_byte(&jpeg_buffer);
790 skip(&jpeg_buffer, 1);
791 }
792
793 skip(&jpeg_buffer, components * 2);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300794 break;
795
796 /* skip payload-less markers */
797 case RST ... RST + 7:
798 case SOI:
799 case EOI:
800 case TEM:
801 break;
802
803 /* skip uninteresting payload markers */
804 default:
805 if (get_word_be(&jpeg_buffer, &word))
806 break;
807 length = (long)word - 2;
808 skip(&jpeg_buffer, length);
809 break;
810 }
811 }
812 result->w = width;
813 result->h = height;
814 result->size = components;
Jacek Anaszewskif8433962013-11-21 13:33:09 -0300815
816 switch (subsampling) {
817 case 0x11:
818 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444;
819 break;
820 case 0x21:
821 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422;
822 break;
823 case 0x22:
824 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420;
825 break;
826 case 0x33:
827 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
828 break;
829 default:
830 return false;
831 }
832
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300833 return !notfound;
834}
835
836static int s5p_jpeg_querycap(struct file *file, void *priv,
837 struct v4l2_capability *cap)
838{
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300839 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300840
841 if (ctx->mode == S5P_JPEG_ENCODE) {
842 strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder",
843 sizeof(cap->driver));
844 strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
845 sizeof(cap->card));
846 } else {
847 strlcpy(cap->driver, S5P_JPEG_M2M_NAME " decoder",
848 sizeof(cap->driver));
849 strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
850 sizeof(cap->card));
851 }
852 cap->bus_info[0] = 0;
Sylwester Nawrockif0476a82012-07-26 09:30:00 -0300853 /*
854 * This is only a mem-to-mem video device. The capture and output
855 * device capability flags are left only for backward compatibility
856 * and are scheduled for removal.
857 */
858 cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M |
859 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300860 return 0;
861}
862
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300863static int enum_fmt(struct s5p_jpeg_fmt *sjpeg_formats, int n,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300864 struct v4l2_fmtdesc *f, u32 type)
865{
866 int i, num = 0;
867
868 for (i = 0; i < n; ++i) {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300869 if (sjpeg_formats[i].flags & type) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300870 /* index-th format of type type found ? */
871 if (num == f->index)
872 break;
873 /* Correct type but haven't reached our index yet,
874 * just increment per-type index */
875 ++num;
876 }
877 }
878
879 /* Format not found */
880 if (i >= n)
881 return -EINVAL;
882
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300883 strlcpy(f->description, sjpeg_formats[i].name, sizeof(f->description));
884 f->pixelformat = sjpeg_formats[i].fourcc;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300885
886 return 0;
887}
888
889static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
890 struct v4l2_fmtdesc *f)
891{
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300892 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300893
894 if (ctx->mode == S5P_JPEG_ENCODE)
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300895 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
896 SJPEG_FMT_FLAG_ENC_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300897
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300898 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
899 SJPEG_FMT_FLAG_DEC_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300900}
901
902static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
903 struct v4l2_fmtdesc *f)
904{
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300905 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300906
907 if (ctx->mode == S5P_JPEG_ENCODE)
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300908 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
909 SJPEG_FMT_FLAG_ENC_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300910
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300911 return enum_fmt(sjpeg_formats, SJPEG_NUM_FORMATS, f,
912 SJPEG_FMT_FLAG_DEC_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300913}
914
915static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
916 enum v4l2_buf_type type)
917{
918 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
919 return &ctx->out_q;
920 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
921 return &ctx->cap_q;
922
923 return NULL;
924}
925
926static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
927{
928 struct vb2_queue *vq;
929 struct s5p_jpeg_q_data *q_data = NULL;
930 struct v4l2_pix_format *pix = &f->fmt.pix;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300931 struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300932
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300933 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300934 if (!vq)
935 return -EINVAL;
936
937 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
938 ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
939 return -EINVAL;
940 q_data = get_q_data(ct, f->type);
941 BUG_ON(q_data == NULL);
942
943 pix->width = q_data->w;
944 pix->height = q_data->h;
945 pix->field = V4L2_FIELD_NONE;
946 pix->pixelformat = q_data->fmt->fourcc;
947 pix->bytesperline = 0;
948 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
949 u32 bpl = q_data->w;
950 if (q_data->fmt->colplanes == 1)
951 bpl = (bpl * q_data->fmt->depth) >> 3;
952 pix->bytesperline = bpl;
953 }
954 pix->sizeimage = q_data->size;
955
956 return 0;
957}
958
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300959static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
960 u32 pixelformat, unsigned int fmt_type)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300961{
Jacek Anaszewskib2451682014-04-10 04:32:11 -0300962 unsigned int k, fmt_flag;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300963
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300964 if (ctx->mode == S5P_JPEG_ENCODE)
965 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
966 SJPEG_FMT_FLAG_ENC_OUTPUT :
967 SJPEG_FMT_FLAG_ENC_CAPTURE;
968 else
969 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
970 SJPEG_FMT_FLAG_DEC_OUTPUT :
971 SJPEG_FMT_FLAG_DEC_CAPTURE;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300972
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300973 for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) {
974 struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k];
975 if (fmt->fourcc == pixelformat &&
976 fmt->flags & fmt_flag &&
Jacek Anaszewskib2451682014-04-10 04:32:11 -0300977 fmt->flags & ctx->jpeg->variant->fmt_ver_flag) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300978 return fmt;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -0300979 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300980 }
981
982 return NULL;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300983}
984
985static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
986 unsigned int walign,
987 u32 *h, unsigned int hmin, unsigned int hmax,
988 unsigned int halign)
989{
990 int width, height, w_step, h_step;
991
992 width = *w;
993 height = *h;
994
995 w_step = 1 << walign;
996 h_step = 1 << halign;
997 v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
998
999 if (*w < width && (*w + w_step) < wmax)
1000 *w += w_step;
1001 if (*h < height && (*h + h_step) < hmax)
1002 *h += h_step;
1003
1004}
1005
1006static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
1007 struct s5p_jpeg_ctx *ctx, int q_type)
1008{
1009 struct v4l2_pix_format *pix = &f->fmt.pix;
1010
1011 if (pix->field == V4L2_FIELD_ANY)
1012 pix->field = V4L2_FIELD_NONE;
1013 else if (pix->field != V4L2_FIELD_NONE)
1014 return -EINVAL;
1015
1016 /* V4L2 specification suggests the driver corrects the format struct
1017 * if any of the dimensions is unsupported */
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001018 if (q_type == FMT_TYPE_OUTPUT)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001019 jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
1020 S5P_JPEG_MAX_WIDTH, 0,
1021 &pix->height, S5P_JPEG_MIN_HEIGHT,
1022 S5P_JPEG_MAX_HEIGHT, 0);
1023 else
1024 jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
1025 S5P_JPEG_MAX_WIDTH, fmt->h_align,
1026 &pix->height, S5P_JPEG_MIN_HEIGHT,
1027 S5P_JPEG_MAX_HEIGHT, fmt->v_align);
1028
1029 if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
1030 if (pix->sizeimage <= 0)
1031 pix->sizeimage = PAGE_SIZE;
1032 pix->bytesperline = 0;
1033 } else {
1034 u32 bpl = pix->bytesperline;
1035
1036 if (fmt->colplanes > 1 && bpl < pix->width)
1037 bpl = pix->width; /* planar */
1038
1039 if (fmt->colplanes == 1 && /* packed */
Jacek Anaszewskicc690902013-11-25 06:58:10 -03001040 (bpl << 3) / fmt->depth < pix->width)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001041 bpl = (pix->width * fmt->depth) >> 3;
1042
1043 pix->bytesperline = bpl;
1044 pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
1045 }
1046
1047 return 0;
1048}
1049
1050static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
1051 struct v4l2_format *f)
1052{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001053 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001054 struct v4l2_pix_format *pix = &f->fmt.pix;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001055 struct s5p_jpeg_fmt *fmt;
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001056 int ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001057
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001058 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1059 FMT_TYPE_CAPTURE);
1060 if (!fmt) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001061 v4l2_err(&ctx->jpeg->v4l2_dev,
1062 "Fourcc format (0x%08x) invalid.\n",
1063 f->fmt.pix.pixelformat);
1064 return -EINVAL;
1065 }
1066
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001067 if ((ctx->jpeg->variant->version != SJPEG_EXYNOS4) ||
1068 (ctx->mode != S5P_JPEG_DECODE))
1069 goto exit;
1070
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001071 /*
1072 * The exynos4x12 device requires resulting YUV image
1073 * subsampling not to be lower than the input jpeg subsampling.
1074 * If this requirement is not met then downgrade the requested
1075 * capture format to the one with subsampling equal to the input jpeg.
1076 */
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001077 if ((fmt->flags & SJPEG_FMT_NON_RGB) &&
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001078 (fmt->subsampling < ctx->subsampling)) {
1079 ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
1080 fmt->fourcc,
1081 &pix->pixelformat,
1082 ctx);
1083 if (ret < 0)
1084 pix->pixelformat = V4L2_PIX_FMT_GREY;
1085
1086 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1087 FMT_TYPE_CAPTURE);
1088 }
1089
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001090 /*
1091 * Decompression of a JPEG file with 4:2:0 subsampling and odd
1092 * width to the YUV 4:2:0 compliant formats produces a raw image
1093 * with broken luma component. Adjust capture format to RGB565
1094 * in such a case.
1095 */
1096 if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
1097 (ctx->out_q.w & 1) &&
1098 (pix->pixelformat == V4L2_PIX_FMT_NV12 ||
1099 pix->pixelformat == V4L2_PIX_FMT_NV21 ||
1100 pix->pixelformat == V4L2_PIX_FMT_YUV420)) {
1101 pix->pixelformat = V4L2_PIX_FMT_RGB565;
1102 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1103 FMT_TYPE_CAPTURE);
1104 }
1105
1106exit:
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001107 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001108}
1109
1110static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
1111 struct v4l2_format *f)
1112{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001113 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001114 struct s5p_jpeg_fmt *fmt;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001115
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001116 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1117 FMT_TYPE_OUTPUT);
1118 if (!fmt) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001119 v4l2_err(&ctx->jpeg->v4l2_dev,
1120 "Fourcc format (0x%08x) invalid.\n",
1121 f->fmt.pix.pixelformat);
1122 return -EINVAL;
1123 }
1124
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001125 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001126}
1127
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001128static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
1129 struct v4l2_format *f,
1130 int fmt_depth)
1131{
1132 struct v4l2_pix_format *pix = &f->fmt.pix;
1133 u32 pix_fmt = f->fmt.pix.pixelformat;
1134 int w = pix->width, h = pix->height, wh_align;
1135
1136 if (pix_fmt == V4L2_PIX_FMT_RGB32 ||
1137 pix_fmt == V4L2_PIX_FMT_NV24 ||
1138 pix_fmt == V4L2_PIX_FMT_NV42 ||
1139 pix_fmt == V4L2_PIX_FMT_NV12 ||
1140 pix_fmt == V4L2_PIX_FMT_NV21 ||
1141 pix_fmt == V4L2_PIX_FMT_YUV420)
1142 wh_align = 4;
1143 else
1144 wh_align = 1;
1145
1146 jpeg_bound_align_image(&w, S5P_JPEG_MIN_WIDTH,
1147 S5P_JPEG_MAX_WIDTH, wh_align,
1148 &h, S5P_JPEG_MIN_HEIGHT,
1149 S5P_JPEG_MAX_HEIGHT, wh_align);
1150
1151 return w * h * fmt_depth >> 3;
1152}
1153
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001154static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
1155{
1156 struct vb2_queue *vq;
1157 struct s5p_jpeg_q_data *q_data = NULL;
1158 struct v4l2_pix_format *pix = &f->fmt.pix;
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001159 struct v4l2_ctrl *ctrl_subs;
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001160 unsigned int f_type;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001161
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001162 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001163 if (!vq)
1164 return -EINVAL;
1165
1166 q_data = get_q_data(ct, f->type);
1167 BUG_ON(q_data == NULL);
1168
1169 if (vb2_is_busy(vq)) {
1170 v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
1171 return -EBUSY;
1172 }
1173
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001174 f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
1175 FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;
1176
1177 q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001178 q_data->w = pix->width;
1179 q_data->h = pix->height;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001180 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
1181 /*
1182 * During encoding Exynos4x12 SoCs access wider memory area
1183 * than it results from Image_x and Image_y values written to
1184 * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu
1185 * page fault calculate proper buffer size in such a case.
1186 */
1187 if (ct->jpeg->variant->version == SJPEG_EXYNOS4 &&
1188 f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)
1189 q_data->size = exynos4_jpeg_get_output_buffer_size(ct,
1190 f,
1191 q_data->fmt->depth);
1192 else
1193 q_data->size = q_data->w * q_data->h *
1194 q_data->fmt->depth >> 3;
1195 } else {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001196 q_data->size = pix->sizeimage;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001197 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001198
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001199 if (f_type == FMT_TYPE_OUTPUT) {
1200 ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler,
1201 V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
1202 if (ctrl_subs)
1203 v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
1204 }
1205
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001206 return 0;
1207}
1208
1209static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
1210 struct v4l2_format *f)
1211{
1212 int ret;
1213
1214 ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
1215 if (ret)
1216 return ret;
1217
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001218 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001219}
1220
1221static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
1222 struct v4l2_format *f)
1223{
1224 int ret;
1225
1226 ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
1227 if (ret)
1228 return ret;
1229
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001230 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001231}
1232
Sachin Kamat9f3bd322012-05-10 03:38:40 -03001233static int s5p_jpeg_g_selection(struct file *file, void *priv,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001234 struct v4l2_selection *s)
1235{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001236 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001237
1238 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
Jacek Anaszewski38a6ef32014-04-10 04:32:15 -03001239 s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001240 return -EINVAL;
1241
1242 /* For JPEG blob active == default == bounds */
1243 switch (s->target) {
Sylwester Nawrockic1334822012-05-20 11:17:12 -03001244 case V4L2_SEL_TGT_CROP:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001245 case V4L2_SEL_TGT_CROP_BOUNDS:
1246 case V4L2_SEL_TGT_CROP_DEFAULT:
Sylwester Nawrockic1334822012-05-20 11:17:12 -03001247 case V4L2_SEL_TGT_COMPOSE:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001248 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1249 s->r.width = ctx->out_q.w;
1250 s->r.height = ctx->out_q.h;
1251 break;
1252 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1253 case V4L2_SEL_TGT_COMPOSE_PADDED:
1254 s->r.width = ctx->cap_q.w;
1255 s->r.height = ctx->cap_q.h;
1256 break;
1257 default:
1258 return -EINVAL;
1259 }
1260 s->r.left = 0;
1261 s->r.top = 0;
1262 return 0;
1263}
1264
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001265/*
1266 * V4L2 controls
1267 */
1268
1269static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001270{
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001271 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1272 struct s5p_jpeg *jpeg = ctx->jpeg;
1273 unsigned long flags;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001274
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001275 switch (ctrl->id) {
1276 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1277 spin_lock_irqsave(&jpeg->slock, flags);
Jacek Anaszewski303b0a92013-12-18 11:14:00 -03001278 ctrl->val = s5p_jpeg_to_user_subsampling(ctx);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001279 spin_unlock_irqrestore(&jpeg->slock, flags);
1280 break;
1281 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001282
1283 return 0;
1284}
1285
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001286static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
1287{
1288 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1289 unsigned long flags;
1290 int ret = 0;
1291
1292 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1293
1294 if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING) {
1295 if (ctx->jpeg->variant->version == SJPEG_S5P)
1296 goto error_free;
1297 /*
1298 * The exynos4x12 device requires input raw image fourcc
1299 * to be V4L2_PIX_FMT_GREY if gray jpeg format
1300 * is to be set.
1301 */
1302 if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
1303 ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
1304 ret = -EINVAL;
1305 goto error_free;
1306 }
1307 /*
1308 * The exynos4x12 device requires resulting jpeg subsampling
1309 * not to be lower than the input raw image subsampling.
1310 */
1311 if (ctx->out_q.fmt->subsampling > ctrl->val)
1312 ctrl->val = ctx->out_q.fmt->subsampling;
1313 }
1314
1315error_free:
1316 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1317 return ret;
1318}
1319
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001320static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001321{
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001322 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1323 unsigned long flags;
1324
1325 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1326
1327 switch (ctrl->id) {
1328 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -03001329 ctx->compr_quality = ctrl->val;
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001330 break;
1331 case V4L2_CID_JPEG_RESTART_INTERVAL:
1332 ctx->restart_interval = ctrl->val;
1333 break;
1334 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1335 ctx->subsampling = ctrl->val;
1336 break;
1337 }
1338
1339 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1340 return 0;
1341}
1342
1343static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {
1344 .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl,
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001345 .try_ctrl = s5p_jpeg_try_ctrl,
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001346 .s_ctrl = s5p_jpeg_s_ctrl,
1347};
1348
1349static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)
1350{
1351 unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */
1352 struct v4l2_ctrl *ctrl;
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001353 int ret;
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001354
1355 v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
1356
1357 if (ctx->mode == S5P_JPEG_ENCODE) {
1358 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1359 V4L2_CID_JPEG_COMPRESSION_QUALITY,
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -03001360 0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001361
1362 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1363 V4L2_CID_JPEG_RESTART_INTERVAL,
1364 0, 3, 0xffff, 0);
Jacek Anaszewskifdf9e2b2013-11-21 13:33:41 -03001365 if (ctx->jpeg->variant->version == SJPEG_S5P)
1366 mask = ~0x06; /* 422, 420 */
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001367 }
1368
1369 ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1370 V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
1371 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,
1372 V4L2_JPEG_CHROMA_SUBSAMPLING_422);
1373
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001374 if (ctx->ctrl_handler.error) {
1375 ret = ctx->ctrl_handler.error;
1376 goto error_free;
1377 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001378
1379 if (ctx->mode == S5P_JPEG_DECODE)
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001380 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |
1381 V4L2_CTRL_FLAG_READ_ONLY;
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001382
1383 ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
1384 if (ret < 0)
1385 goto error_free;
1386
1387 return ret;
1388
1389error_free:
1390 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1391 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001392}
1393
1394static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
1395 .vidioc_querycap = s5p_jpeg_querycap,
1396
1397 .vidioc_enum_fmt_vid_cap = s5p_jpeg_enum_fmt_vid_cap,
1398 .vidioc_enum_fmt_vid_out = s5p_jpeg_enum_fmt_vid_out,
1399
1400 .vidioc_g_fmt_vid_cap = s5p_jpeg_g_fmt,
1401 .vidioc_g_fmt_vid_out = s5p_jpeg_g_fmt,
1402
1403 .vidioc_try_fmt_vid_cap = s5p_jpeg_try_fmt_vid_cap,
1404 .vidioc_try_fmt_vid_out = s5p_jpeg_try_fmt_vid_out,
1405
1406 .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap,
1407 .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out,
1408
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001409 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1410 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1411 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1412 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001413
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001414 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
1415 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001416
1417 .vidioc_g_selection = s5p_jpeg_g_selection,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001418};
1419
1420/*
1421 * ============================================================================
1422 * mem2mem callbacks
1423 * ============================================================================
1424 */
1425
1426static void s5p_jpeg_device_run(void *priv)
1427{
1428 struct s5p_jpeg_ctx *ctx = priv;
1429 struct s5p_jpeg *jpeg = ctx->jpeg;
1430 struct vb2_buffer *src_buf, *dst_buf;
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03001431 unsigned long src_addr, dst_addr, flags;
1432
1433 spin_lock_irqsave(&ctx->jpeg->slock, flags);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001434
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001435 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1436 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001437 src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
1438 dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
1439
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001440 s5p_jpeg_reset(jpeg->regs);
1441 s5p_jpeg_poweron(jpeg->regs);
1442 s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001443 if (ctx->mode == S5P_JPEG_ENCODE) {
1444 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001445 s5p_jpeg_input_raw_mode(jpeg->regs,
1446 S5P_JPEG_RAW_IN_565);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001447 else
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001448 s5p_jpeg_input_raw_mode(jpeg->regs,
1449 S5P_JPEG_RAW_IN_422);
1450 s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
1451 s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);
1452 s5p_jpeg_x(jpeg->regs, ctx->out_q.w);
1453 s5p_jpeg_y(jpeg->regs, ctx->out_q.h);
1454 s5p_jpeg_imgadr(jpeg->regs, src_addr);
1455 s5p_jpeg_jpgadr(jpeg->regs, dst_addr);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001456
1457 /* ultimately comes from sizeimage from userspace */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001458 s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001459
1460 /* JPEG RGB to YCbCr conversion matrix */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001461 s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
1462 s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
1463 s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
1464 s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
1465 s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
1466 s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
1467 s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
1468 s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
1469 s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001470
1471 /*
1472 * JPEG IP allows storing 4 quantization tables
1473 * We fill table 0 for luma and table 1 for chroma
1474 */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03001475 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1476 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001477 /* use table 0 for Y */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001478 s5p_jpeg_qtbl(jpeg->regs, 1, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001479 /* use table 1 for Cb and Cr*/
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001480 s5p_jpeg_qtbl(jpeg->regs, 2, 1);
1481 s5p_jpeg_qtbl(jpeg->regs, 3, 1);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001482
1483 /* Y, Cb, Cr use Huffman table 0 */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001484 s5p_jpeg_htbl_ac(jpeg->regs, 1);
1485 s5p_jpeg_htbl_dc(jpeg->regs, 1);
1486 s5p_jpeg_htbl_ac(jpeg->regs, 2);
1487 s5p_jpeg_htbl_dc(jpeg->regs, 2);
1488 s5p_jpeg_htbl_ac(jpeg->regs, 3);
1489 s5p_jpeg_htbl_dc(jpeg->regs, 3);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001490 } else { /* S5P_JPEG_DECODE */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001491 s5p_jpeg_rst_int_enable(jpeg->regs, true);
1492 s5p_jpeg_data_num_int_enable(jpeg->regs, true);
1493 s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001494 if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001495 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001496 else
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001497 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
1498 s5p_jpeg_jpgadr(jpeg->regs, src_addr);
1499 s5p_jpeg_imgadr(jpeg->regs, dst_addr);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001500 }
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001501
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001502 s5p_jpeg_start(jpeg->regs);
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03001503
1504 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001505}
1506
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001507static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
1508{
1509 struct s5p_jpeg *jpeg = ctx->jpeg;
1510 struct s5p_jpeg_fmt *fmt;
1511 struct vb2_buffer *vb;
1512 struct s5p_jpeg_addr jpeg_addr;
1513 u32 pix_size, padding_bytes = 0;
1514
1515 pix_size = ctx->cap_q.w * ctx->cap_q.h;
1516
1517 if (ctx->mode == S5P_JPEG_ENCODE) {
1518 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1519 fmt = ctx->out_q.fmt;
1520 if (ctx->out_q.w % 2 && fmt->h_align > 0)
1521 padding_bytes = ctx->out_q.h;
1522 } else {
1523 fmt = ctx->cap_q.fmt;
1524 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1525 }
1526
1527 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
1528
1529 if (fmt->colplanes == 2) {
1530 jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;
1531 } else if (fmt->colplanes == 3) {
1532 jpeg_addr.cb = jpeg_addr.y + pix_size;
1533 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
1534 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
1535 else
1536 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
1537 }
1538
1539 exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);
1540}
1541
1542static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
1543{
1544 struct s5p_jpeg *jpeg = ctx->jpeg;
1545 struct vb2_buffer *vb;
1546 unsigned int jpeg_addr = 0;
1547
1548 if (ctx->mode == S5P_JPEG_ENCODE)
1549 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1550 else
1551 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1552
1553 jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1554 exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
1555}
1556
1557static void exynos4_jpeg_device_run(void *priv)
1558{
1559 struct s5p_jpeg_ctx *ctx = priv;
1560 struct s5p_jpeg *jpeg = ctx->jpeg;
1561 unsigned int bitstream_size;
1562 unsigned long flags;
1563
1564 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1565
1566 if (ctx->mode == S5P_JPEG_ENCODE) {
1567 exynos4_jpeg_sw_reset(jpeg->regs);
1568 exynos4_jpeg_set_interrupt(jpeg->regs);
1569 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
1570
1571 exynos4_jpeg_set_huff_tbl(jpeg->regs);
1572
1573 /*
1574 * JPEG IP allows storing 4 quantization tables
1575 * We fill table 0 for luma and table 1 for chroma
1576 */
1577 exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
1578 exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
1579
1580 exynos4_jpeg_set_encode_tbl_select(jpeg->regs,
1581 ctx->compr_quality);
1582 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
1583 ctx->cap_q.h);
1584
1585 exynos4_jpeg_set_enc_out_fmt(jpeg->regs, ctx->subsampling);
1586 exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->out_q.fmt->fourcc);
1587 exynos4_jpeg_set_img_addr(ctx);
1588 exynos4_jpeg_set_jpeg_addr(ctx);
1589 exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
1590 ctx->out_q.fmt->fourcc);
1591 } else {
1592 exynos4_jpeg_sw_reset(jpeg->regs);
1593 exynos4_jpeg_set_interrupt(jpeg->regs);
1594 exynos4_jpeg_set_img_addr(ctx);
1595 exynos4_jpeg_set_jpeg_addr(ctx);
1596 exynos4_jpeg_set_img_fmt(jpeg->regs, ctx->cap_q.fmt->fourcc);
1597
1598 bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
1599
1600 exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
1601 }
1602
1603 exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
1604
1605 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1606}
1607
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001608static int s5p_jpeg_job_ready(void *priv)
1609{
1610 struct s5p_jpeg_ctx *ctx = priv;
1611
1612 if (ctx->mode == S5P_JPEG_DECODE)
1613 return ctx->hdr_parsed;
1614 return 1;
1615}
1616
1617static void s5p_jpeg_job_abort(void *priv)
1618{
1619}
1620
1621static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
1622 .device_run = s5p_jpeg_device_run,
1623 .job_ready = s5p_jpeg_job_ready,
1624 .job_abort = s5p_jpeg_job_abort,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001625}
1626;
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03001627static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001628 .device_run = exynos4_jpeg_device_run,
1629 .job_ready = s5p_jpeg_job_ready,
1630 .job_abort = s5p_jpeg_job_abort,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001631};
1632
1633/*
1634 * ============================================================================
1635 * Queue operations
1636 * ============================================================================
1637 */
1638
Marek Szyprowski719c1742012-01-13 05:12:38 -03001639static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
1640 const struct v4l2_format *fmt,
1641 unsigned int *nbuffers, unsigned int *nplanes,
1642 unsigned int sizes[], void *alloc_ctxs[])
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001643{
1644 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
1645 struct s5p_jpeg_q_data *q_data = NULL;
1646 unsigned int size, count = *nbuffers;
1647
1648 q_data = get_q_data(ctx, vq->type);
1649 BUG_ON(q_data == NULL);
1650
1651 size = q_data->size;
1652
1653 /*
1654 * header is parsed during decoding and parsed information stored
1655 * in the context so we do not allow another buffer to overwrite it
1656 */
1657 if (ctx->mode == S5P_JPEG_DECODE)
1658 count = 1;
1659
1660 *nbuffers = count;
1661 *nplanes = 1;
1662 sizes[0] = size;
1663 alloc_ctxs[0] = ctx->jpeg->alloc_ctx;
1664
1665 return 0;
1666}
1667
1668static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
1669{
1670 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1671 struct s5p_jpeg_q_data *q_data = NULL;
1672
1673 q_data = get_q_data(ctx, vb->vb2_queue->type);
1674 BUG_ON(q_data == NULL);
1675
1676 if (vb2_plane_size(vb, 0) < q_data->size) {
1677 pr_err("%s data will not fit into plane (%lu < %lu)\n",
1678 __func__, vb2_plane_size(vb, 0),
1679 (long)q_data->size);
1680 return -EINVAL;
1681 }
1682
1683 vb2_set_plane_payload(vb, 0, q_data->size);
1684
1685 return 0;
1686}
1687
1688static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
1689{
1690 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1691
1692 if (ctx->mode == S5P_JPEG_DECODE &&
1693 vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1694 struct s5p_jpeg_q_data tmp, *q_data;
1695 ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
1696 (unsigned long)vb2_plane_vaddr(vb, 0),
1697 min((unsigned long)ctx->out_q.size,
Jacek Anaszewskif8433962013-11-21 13:33:09 -03001698 vb2_get_plane_payload(vb, 0)), ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001699 if (!ctx->hdr_parsed) {
1700 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
1701 return;
1702 }
1703
1704 q_data = &ctx->out_q;
1705 q_data->w = tmp.w;
1706 q_data->h = tmp.h;
1707
1708 q_data = &ctx->cap_q;
1709 q_data->w = tmp.w;
1710 q_data->h = tmp.h;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001711 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001712
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001713 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001714}
1715
1716static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
1717{
1718 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
1719 int ret;
1720
1721 ret = pm_runtime_get_sync(ctx->jpeg->dev);
1722
1723 return ret > 0 ? 0 : ret;
1724}
1725
Hans Verkuile37559b2014-04-17 02:47:21 -03001726static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001727{
1728 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
1729
1730 pm_runtime_put(ctx->jpeg->dev);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001731}
1732
1733static struct vb2_ops s5p_jpeg_qops = {
1734 .queue_setup = s5p_jpeg_queue_setup,
1735 .buf_prepare = s5p_jpeg_buf_prepare,
1736 .buf_queue = s5p_jpeg_buf_queue,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001737 .wait_prepare = vb2_ops_wait_prepare,
1738 .wait_finish = vb2_ops_wait_finish,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001739 .start_streaming = s5p_jpeg_start_streaming,
1740 .stop_streaming = s5p_jpeg_stop_streaming,
1741};
1742
1743static int queue_init(void *priv, struct vb2_queue *src_vq,
1744 struct vb2_queue *dst_vq)
1745{
1746 struct s5p_jpeg_ctx *ctx = priv;
1747 int ret;
1748
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001749 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1750 src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
1751 src_vq->drv_priv = ctx;
1752 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1753 src_vq->ops = &s5p_jpeg_qops;
1754 src_vq->mem_ops = &vb2_dma_contig_memops;
Sakari Ailusade48682014-02-25 19:12:19 -03001755 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001756 src_vq->lock = &ctx->jpeg->lock;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001757
1758 ret = vb2_queue_init(src_vq);
1759 if (ret)
1760 return ret;
1761
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001762 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1763 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
1764 dst_vq->drv_priv = ctx;
1765 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1766 dst_vq->ops = &s5p_jpeg_qops;
1767 dst_vq->mem_ops = &vb2_dma_contig_memops;
Sakari Ailusade48682014-02-25 19:12:19 -03001768 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001769 dst_vq->lock = &ctx->jpeg->lock;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001770
1771 return vb2_queue_init(dst_vq);
1772}
1773
1774/*
1775 * ============================================================================
1776 * ISR
1777 * ============================================================================
1778 */
1779
1780static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
1781{
1782 struct s5p_jpeg *jpeg = dev_id;
1783 struct s5p_jpeg_ctx *curr_ctx;
1784 struct vb2_buffer *src_buf, *dst_buf;
1785 unsigned long payload_size = 0;
1786 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
1787 bool enc_jpeg_too_large = false;
1788 bool timer_elapsed = false;
1789 bool op_completed = false;
1790
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001791 spin_lock(&jpeg->slock);
1792
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001793 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
1794
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001795 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
1796 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001797
1798 if (curr_ctx->mode == S5P_JPEG_ENCODE)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001799 enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);
1800 timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);
1801 op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001802 if (curr_ctx->mode == S5P_JPEG_DECODE)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001803 op_completed = op_completed &&
1804 s5p_jpeg_stream_stat_ok(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001805
1806 if (enc_jpeg_too_large) {
1807 state = VB2_BUF_STATE_ERROR;
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001808 s5p_jpeg_clear_enc_stream_stat(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001809 } else if (timer_elapsed) {
1810 state = VB2_BUF_STATE_ERROR;
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001811 s5p_jpeg_clear_timer_stat(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001812 } else if (!op_completed) {
1813 state = VB2_BUF_STATE_ERROR;
1814 } else {
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001815 payload_size = s5p_jpeg_compressed_size(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001816 }
1817
Kamil Debskiaca326a2013-04-24 10:08:02 -03001818 dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
1819 dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
Sakari Ailus309f4d62014-02-08 14:21:35 -03001820 dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
1821 dst_buf->v4l2_buf.flags |=
1822 src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
Kamil Debskiaca326a2013-04-24 10:08:02 -03001823
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001824 v4l2_m2m_buf_done(src_buf, state);
1825 if (curr_ctx->mode == S5P_JPEG_ENCODE)
1826 vb2_set_plane_payload(dst_buf, 0, payload_size);
1827 v4l2_m2m_buf_done(dst_buf, state);
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001828 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001829
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001830 curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001831 spin_unlock(&jpeg->slock);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03001832
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03001833 s5p_jpeg_clear_int(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001834
1835 return IRQ_HANDLED;
1836}
1837
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001838static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
1839{
1840 unsigned int int_status;
1841 struct vb2_buffer *src_vb, *dst_vb;
1842 struct s5p_jpeg *jpeg = priv;
1843 struct s5p_jpeg_ctx *curr_ctx;
1844 unsigned long payload_size = 0;
1845
1846 spin_lock(&jpeg->slock);
1847
1848 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
1849
1850 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
1851 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
1852
1853 int_status = exynos4_jpeg_get_int_status(jpeg->regs);
1854
1855 if (int_status) {
1856 switch (int_status & 0x1f) {
1857 case 0x1:
1858 jpeg->irq_ret = ERR_PROT;
1859 break;
1860 case 0x2:
1861 jpeg->irq_ret = OK_ENC_OR_DEC;
1862 break;
1863 case 0x4:
1864 jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;
1865 break;
1866 case 0x8:
1867 jpeg->irq_ret = ERR_MULTI_SCAN;
1868 break;
1869 case 0x10:
1870 jpeg->irq_ret = ERR_FRAME;
1871 break;
1872 default:
1873 jpeg->irq_ret = ERR_UNKNOWN;
1874 break;
1875 }
1876 } else {
1877 jpeg->irq_ret = ERR_UNKNOWN;
1878 }
1879
1880 if (jpeg->irq_ret == OK_ENC_OR_DEC) {
1881 if (curr_ctx->mode == S5P_JPEG_ENCODE) {
1882 payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
1883 vb2_set_plane_payload(dst_vb, 0, payload_size);
1884 }
1885 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
1886 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
1887 } else {
1888 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
1889 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
1890 }
1891
1892 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
1893 curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
1894
1895 spin_unlock(&jpeg->slock);
1896 return IRQ_HANDLED;
1897}
1898
1899static void *jpeg_get_drv_data(struct platform_device *pdev);
1900
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001901/*
1902 * ============================================================================
1903 * Driver basic infrastructure
1904 * ============================================================================
1905 */
1906
1907static int s5p_jpeg_probe(struct platform_device *pdev)
1908{
1909 struct s5p_jpeg *jpeg;
1910 struct resource *res;
1911 int ret;
1912
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001913 if (!pdev->dev.of_node)
1914 return -ENODEV;
1915
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001916 /* JPEG IP abstraction struct */
Sachin Kamat5b58b952012-05-14 06:33:34 -03001917 jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001918 if (!jpeg)
1919 return -ENOMEM;
1920
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001921 jpeg->variant = jpeg_get_drv_data(pdev);
1922
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001923 mutex_init(&jpeg->lock);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001924 spin_lock_init(&jpeg->slock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001925 jpeg->dev = &pdev->dev;
1926
1927 /* memory-mapped registers */
1928 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001929
Thierry Redingf23999e2013-01-21 06:09:07 -03001930 jpeg->regs = devm_ioremap_resource(&pdev->dev, res);
1931 if (IS_ERR(jpeg->regs))
1932 return PTR_ERR(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001933
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001934 /* interrupt service routine registration */
1935 jpeg->irq = ret = platform_get_irq(pdev, 0);
1936 if (ret < 0) {
1937 dev_err(&pdev->dev, "cannot find IRQ\n");
Sachin Kamat5b58b952012-05-14 06:33:34 -03001938 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001939 }
1940
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03001941 ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,
1942 0, dev_name(&pdev->dev), jpeg);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001943 if (ret) {
1944 dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
Sachin Kamat5b58b952012-05-14 06:33:34 -03001945 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001946 }
1947
1948 /* clocks */
1949 jpeg->clk = clk_get(&pdev->dev, "jpeg");
1950 if (IS_ERR(jpeg->clk)) {
1951 dev_err(&pdev->dev, "cannot get clock\n");
1952 ret = PTR_ERR(jpeg->clk);
Sachin Kamat5b58b952012-05-14 06:33:34 -03001953 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001954 }
1955 dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001956
1957 /* v4l2 device */
1958 ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
1959 if (ret) {
1960 dev_err(&pdev->dev, "Failed to register v4l2 device\n");
1961 goto clk_get_rollback;
1962 }
1963
1964 /* mem2mem device */
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03001965 jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001966 if (IS_ERR(jpeg->m2m_dev)) {
1967 v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
1968 ret = PTR_ERR(jpeg->m2m_dev);
1969 goto device_register_rollback;
1970 }
1971
1972 jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1973 if (IS_ERR(jpeg->alloc_ctx)) {
1974 v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
1975 ret = PTR_ERR(jpeg->alloc_ctx);
1976 goto m2m_init_rollback;
1977 }
1978
1979 /* JPEG encoder /dev/videoX node */
1980 jpeg->vfd_encoder = video_device_alloc();
1981 if (!jpeg->vfd_encoder) {
1982 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
1983 ret = -ENOMEM;
1984 goto vb2_allocator_rollback;
1985 }
Seung-Woo Kimbaaf0462013-10-10 04:45:56 -03001986 snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),
1987 "%s-enc", S5P_JPEG_M2M_NAME);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001988 jpeg->vfd_encoder->fops = &s5p_jpeg_fops;
1989 jpeg->vfd_encoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
1990 jpeg->vfd_encoder->minor = -1;
1991 jpeg->vfd_encoder->release = video_device_release;
1992 jpeg->vfd_encoder->lock = &jpeg->lock;
1993 jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev;
Hans Verkuil954f3402012-09-05 06:05:50 -03001994 jpeg->vfd_encoder->vfl_dir = VFL_DIR_M2M;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001995
1996 ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
1997 if (ret) {
1998 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
1999 goto enc_vdev_alloc_rollback;
2000 }
2001
2002 video_set_drvdata(jpeg->vfd_encoder, jpeg);
2003 v4l2_info(&jpeg->v4l2_dev,
2004 "encoder device registered as /dev/video%d\n",
2005 jpeg->vfd_encoder->num);
2006
2007 /* JPEG decoder /dev/videoX node */
2008 jpeg->vfd_decoder = video_device_alloc();
2009 if (!jpeg->vfd_decoder) {
2010 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2011 ret = -ENOMEM;
2012 goto enc_vdev_register_rollback;
2013 }
Seung-Woo Kimbaaf0462013-10-10 04:45:56 -03002014 snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),
2015 "%s-dec", S5P_JPEG_M2M_NAME);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002016 jpeg->vfd_decoder->fops = &s5p_jpeg_fops;
2017 jpeg->vfd_decoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2018 jpeg->vfd_decoder->minor = -1;
2019 jpeg->vfd_decoder->release = video_device_release;
2020 jpeg->vfd_decoder->lock = &jpeg->lock;
2021 jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev;
Jacek Anaszewski7f7d8fe2013-09-11 06:17:45 -03002022 jpeg->vfd_decoder->vfl_dir = VFL_DIR_M2M;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002023
2024 ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
2025 if (ret) {
2026 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
2027 goto dec_vdev_alloc_rollback;
2028 }
2029
2030 video_set_drvdata(jpeg->vfd_decoder, jpeg);
2031 v4l2_info(&jpeg->v4l2_dev,
2032 "decoder device registered as /dev/video%d\n",
2033 jpeg->vfd_decoder->num);
2034
2035 /* final statements & power management */
2036 platform_set_drvdata(pdev, jpeg);
2037
2038 pm_runtime_enable(&pdev->dev);
2039
2040 v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
2041
2042 return 0;
2043
2044dec_vdev_alloc_rollback:
2045 video_device_release(jpeg->vfd_decoder);
2046
2047enc_vdev_register_rollback:
2048 video_unregister_device(jpeg->vfd_encoder);
2049
2050enc_vdev_alloc_rollback:
2051 video_device_release(jpeg->vfd_encoder);
2052
2053vb2_allocator_rollback:
2054 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
2055
2056m2m_init_rollback:
2057 v4l2_m2m_release(jpeg->m2m_dev);
2058
2059device_register_rollback:
2060 v4l2_device_unregister(&jpeg->v4l2_dev);
2061
2062clk_get_rollback:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002063 clk_put(jpeg->clk);
2064
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002065 return ret;
2066}
2067
2068static int s5p_jpeg_remove(struct platform_device *pdev)
2069{
2070 struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
2071
2072 pm_runtime_disable(jpeg->dev);
2073
2074 video_unregister_device(jpeg->vfd_decoder);
2075 video_device_release(jpeg->vfd_decoder);
2076 video_unregister_device(jpeg->vfd_encoder);
2077 video_device_release(jpeg->vfd_encoder);
2078 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
2079 v4l2_m2m_release(jpeg->m2m_dev);
2080 v4l2_device_unregister(&jpeg->v4l2_dev);
2081
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002082 if (!pm_runtime_status_suspended(&pdev->dev))
2083 clk_disable_unprepare(jpeg->clk);
2084
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002085 clk_put(jpeg->clk);
2086
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002087 return 0;
2088}
2089
2090static int s5p_jpeg_runtime_suspend(struct device *dev)
2091{
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002092 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
2093
2094 clk_disable_unprepare(jpeg->clk);
2095
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002096 return 0;
2097}
2098
2099static int s5p_jpeg_runtime_resume(struct device *dev)
2100{
2101 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002102 unsigned long flags;
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002103 int ret;
2104
2105 ret = clk_prepare_enable(jpeg->clk);
2106 if (ret < 0)
2107 return ret;
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03002108
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002109 spin_lock_irqsave(&jpeg->slock, flags);
2110
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002111 /*
2112 * JPEG IP allows storing two Huffman tables for each component
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002113 * We fill table 0 for each component and do this here only
2114 * for S5PC210 device as Exynos4x12 requires programming its
2115 * Huffman tables each time the encoding process is initialized.
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002116 */
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002117 if (jpeg->variant->version == SJPEG_S5P) {
2118 s5p_jpeg_set_hdctbl(jpeg->regs);
2119 s5p_jpeg_set_hdctblg(jpeg->regs);
2120 s5p_jpeg_set_hactbl(jpeg->regs);
2121 s5p_jpeg_set_hactblg(jpeg->regs);
2122 }
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03002123
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002124 spin_unlock_irqrestore(&jpeg->slock, flags);
2125
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002126 return 0;
2127}
2128
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002129static int s5p_jpeg_suspend(struct device *dev)
2130{
2131 if (pm_runtime_suspended(dev))
2132 return 0;
2133
2134 return s5p_jpeg_runtime_suspend(dev);
2135}
2136
2137static int s5p_jpeg_resume(struct device *dev)
2138{
2139 if (pm_runtime_suspended(dev))
2140 return 0;
2141
2142 return s5p_jpeg_runtime_resume(dev);
2143}
2144
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002145static const struct dev_pm_ops s5p_jpeg_pm_ops = {
Jacek Anaszewskif1347132013-11-25 06:58:13 -03002146 SET_SYSTEM_SLEEP_PM_OPS(s5p_jpeg_suspend, s5p_jpeg_resume)
2147 SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume, NULL)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002148};
2149
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03002150#ifdef CONFIG_OF
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002151static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
2152 .version = SJPEG_S5P,
2153 .jpeg_irq = s5p_jpeg_irq,
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002154 .m2m_ops = &s5p_jpeg_m2m_ops,
Jacek Anaszewskib2451682014-04-10 04:32:11 -03002155 .fmt_ver_flag = SJPEG_FMT_FLAG_S5P,
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03002156};
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002157
2158static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
2159 .version = SJPEG_EXYNOS4,
2160 .jpeg_irq = exynos4_jpeg_irq,
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002161 .m2m_ops = &exynos4_jpeg_m2m_ops,
Jacek Anaszewskib2451682014-04-10 04:32:11 -03002162 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002163};
2164
2165static const struct of_device_id samsung_jpeg_match[] = {
2166 {
2167 .compatible = "samsung,s5pv210-jpeg",
2168 .data = &s5p_jpeg_drvdata,
2169 }, {
2170 .compatible = "samsung,exynos4210-jpeg",
2171 .data = &s5p_jpeg_drvdata,
2172 }, {
2173 .compatible = "samsung,exynos4212-jpeg",
2174 .data = &exynos4_jpeg_drvdata,
2175 },
2176 {},
2177};
2178
2179MODULE_DEVICE_TABLE(of, samsung_jpeg_match);
2180
2181static void *jpeg_get_drv_data(struct platform_device *pdev)
2182{
2183 struct s5p_jpeg_variant *driver_data = NULL;
2184 const struct of_device_id *match;
2185
2186 match = of_match_node(of_match_ptr(samsung_jpeg_match),
2187 pdev->dev.of_node);
2188 if (match)
2189 driver_data = (struct s5p_jpeg_variant *)match->data;
2190
2191 return driver_data;
2192}
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03002193#endif
2194
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002195static struct platform_driver s5p_jpeg_driver = {
2196 .probe = s5p_jpeg_probe,
2197 .remove = s5p_jpeg_remove,
2198 .driver = {
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002199 .of_match_table = of_match_ptr(samsung_jpeg_match),
2200 .owner = THIS_MODULE,
2201 .name = S5P_JPEG_M2M_NAME,
2202 .pm = &s5p_jpeg_pm_ops,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002203 },
2204};
2205
Sachin Kamat87e94292012-07-03 05:54:33 -03002206module_platform_driver(s5p_jpeg_driver);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002207
2208MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
Jacek Anaszewski80529ae2013-12-18 11:04:44 -03002209MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002210MODULE_DESCRIPTION("Samsung JPEG codec driver");
2211MODULE_LICENSE("GPL");