blob: 026111505f5a55974e56f649240d227cfba51a92 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Mauro Carvalho Chehab2c3fb082012-08-14 17:31:16 -03002/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003 *
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03004 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03005 * http://www.samsung.com
6 *
Andrzej Pietrasiewicz66e988e2018-12-13 08:31:07 -05007 * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03008 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03009 */
10
11#include <linux/clk.h>
12#include <linux/err.h>
13#include <linux/gfp.h>
14#include <linux/interrupt.h>
15#include <linux/io.h>
16#include <linux/kernel.h>
17#include <linux/module.h>
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -030018#include <linux/of.h>
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030019#include <linux/platform_device.h>
20#include <linux/pm_runtime.h>
21#include <linux/slab.h>
22#include <linux/spinlock.h>
23#include <linux/string.h>
henryhsu1c84e7f2017-06-30 10:15:46 -040024#include <media/v4l2-event.h>
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030025#include <media/v4l2-mem2mem.h>
26#include <media/v4l2-ioctl.h>
Benoit Parrot030b1612020-05-28 15:26:05 +020027#include <media/v4l2-rect.h>
Junghak Sungc1399902015-09-22 10:30:29 -030028#include <media/videobuf2-v4l2.h>
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030029#include <media/videobuf2-dma-contig.h>
30
31#include "jpeg-core.h"
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -030032#include "jpeg-hw-s5p.h"
Jacek Anaszewski80529ae52013-12-18 11:04:44 -030033#include "jpeg-hw-exynos4.h"
Jacek Anaszewski3246fda2014-07-11 12:19:42 -030034#include "jpeg-hw-exynos3250.h"
Jacek Anaszewski80529ae52013-12-18 11:04:44 -030035#include "jpeg-regs.h"
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030036
Jacek Anaszewski80529ae52013-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 .fourcc = V4L2_PIX_FMT_JPEG,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -030040 .flags = SJPEG_FMT_FLAG_ENC_CAPTURE |
41 SJPEG_FMT_FLAG_DEC_OUTPUT |
42 SJPEG_FMT_FLAG_S5P |
Jacek Anaszewski3246fda2014-07-11 12:19:42 -030043 SJPEG_FMT_FLAG_EXYNOS3250 |
Jacek Anaszewski80529ae52013-12-18 11:04:44 -030044 SJPEG_FMT_FLAG_EXYNOS4,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030045 },
46 {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030047 .fourcc = V4L2_PIX_FMT_YUYV,
48 .depth = 16,
49 .colplanes = 1,
50 .h_align = 4,
51 .v_align = 3,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -030052 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
53 SJPEG_FMT_FLAG_DEC_CAPTURE |
54 SJPEG_FMT_FLAG_S5P |
55 SJPEG_FMT_NON_RGB,
56 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030057 },
58 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -030059 .fourcc = V4L2_PIX_FMT_YUYV,
60 .depth = 16,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -030061 .colplanes = 1,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -030062 .h_align = 1,
63 .v_align = 0,
64 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
65 SJPEG_FMT_FLAG_DEC_CAPTURE |
66 SJPEG_FMT_FLAG_EXYNOS4 |
67 SJPEG_FMT_NON_RGB,
68 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
69 },
70 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -030071 .fourcc = V4L2_PIX_FMT_YUYV,
72 .depth = 16,
73 .colplanes = 1,
74 .h_align = 2,
75 .v_align = 0,
76 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
77 SJPEG_FMT_FLAG_DEC_CAPTURE |
78 SJPEG_FMT_FLAG_EXYNOS3250 |
79 SJPEG_FMT_NON_RGB,
80 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
81 },
82 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -030083 .fourcc = V4L2_PIX_FMT_YVYU,
84 .depth = 16,
85 .colplanes = 1,
86 .h_align = 1,
87 .v_align = 0,
88 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
89 SJPEG_FMT_FLAG_DEC_CAPTURE |
90 SJPEG_FMT_FLAG_EXYNOS4 |
91 SJPEG_FMT_NON_RGB,
92 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
93 },
94 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -030095 .fourcc = V4L2_PIX_FMT_YVYU,
96 .depth = 16,
97 .colplanes = 1,
98 .h_align = 2,
99 .v_align = 0,
100 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
101 SJPEG_FMT_FLAG_DEC_CAPTURE |
102 SJPEG_FMT_FLAG_EXYNOS3250 |
103 SJPEG_FMT_NON_RGB,
104 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
105 },
106 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300107 .fourcc = V4L2_PIX_FMT_UYVY,
108 .depth = 16,
109 .colplanes = 1,
110 .h_align = 2,
111 .v_align = 0,
112 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
113 SJPEG_FMT_FLAG_DEC_CAPTURE |
114 SJPEG_FMT_FLAG_EXYNOS3250 |
115 SJPEG_FMT_NON_RGB,
116 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
117 },
118 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300119 .fourcc = V4L2_PIX_FMT_VYUY,
120 .depth = 16,
121 .colplanes = 1,
122 .h_align = 2,
123 .v_align = 0,
124 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
125 SJPEG_FMT_FLAG_DEC_CAPTURE |
126 SJPEG_FMT_FLAG_EXYNOS3250 |
127 SJPEG_FMT_NON_RGB,
128 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
129 },
130 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300131 .fourcc = V4L2_PIX_FMT_RGB565,
132 .depth = 16,
133 .colplanes = 1,
134 .h_align = 0,
135 .v_align = 0,
136 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
137 SJPEG_FMT_FLAG_DEC_CAPTURE |
138 SJPEG_FMT_FLAG_EXYNOS4 |
139 SJPEG_FMT_RGB,
140 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
141 },
142 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300143 .fourcc = V4L2_PIX_FMT_RGB565,
144 .depth = 16,
145 .colplanes = 1,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300146 .h_align = 2,
147 .v_align = 0,
148 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
149 SJPEG_FMT_FLAG_DEC_CAPTURE |
150 SJPEG_FMT_FLAG_EXYNOS3250 |
151 SJPEG_FMT_RGB,
152 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
153 },
154 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300155 .fourcc = V4L2_PIX_FMT_RGB565X,
156 .depth = 16,
157 .colplanes = 1,
158 .h_align = 2,
159 .v_align = 0,
160 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
161 SJPEG_FMT_FLAG_DEC_CAPTURE |
162 SJPEG_FMT_FLAG_EXYNOS3250 |
163 SJPEG_FMT_RGB,
164 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
165 },
166 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300167 .fourcc = V4L2_PIX_FMT_RGB565,
168 .depth = 16,
169 .colplanes = 1,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300170 .h_align = 0,
171 .v_align = 0,
172 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
173 SJPEG_FMT_FLAG_S5P |
174 SJPEG_FMT_RGB,
175 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
176 },
177 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300178 .fourcc = V4L2_PIX_FMT_RGB32,
179 .depth = 32,
180 .colplanes = 1,
181 .h_align = 0,
182 .v_align = 0,
183 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
184 SJPEG_FMT_FLAG_DEC_CAPTURE |
185 SJPEG_FMT_FLAG_EXYNOS4 |
186 SJPEG_FMT_RGB,
187 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
188 },
189 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300190 .fourcc = V4L2_PIX_FMT_RGB32,
191 .depth = 32,
192 .colplanes = 1,
193 .h_align = 2,
194 .v_align = 0,
195 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
196 SJPEG_FMT_FLAG_DEC_CAPTURE |
197 SJPEG_FMT_FLAG_EXYNOS3250 |
198 SJPEG_FMT_RGB,
199 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
200 },
201 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300202 .fourcc = V4L2_PIX_FMT_NV24,
203 .depth = 24,
204 .colplanes = 2,
205 .h_align = 0,
206 .v_align = 0,
207 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
208 SJPEG_FMT_FLAG_DEC_CAPTURE |
209 SJPEG_FMT_FLAG_EXYNOS4 |
210 SJPEG_FMT_NON_RGB,
211 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
212 },
213 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300214 .fourcc = V4L2_PIX_FMT_NV42,
215 .depth = 24,
216 .colplanes = 2,
217 .h_align = 0,
218 .v_align = 0,
219 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
220 SJPEG_FMT_FLAG_DEC_CAPTURE |
221 SJPEG_FMT_FLAG_EXYNOS4 |
222 SJPEG_FMT_NON_RGB,
223 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
224 },
225 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300226 .fourcc = V4L2_PIX_FMT_NV61,
227 .depth = 16,
228 .colplanes = 2,
229 .h_align = 1,
230 .v_align = 0,
231 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
232 SJPEG_FMT_FLAG_DEC_CAPTURE |
233 SJPEG_FMT_FLAG_EXYNOS4 |
234 SJPEG_FMT_NON_RGB,
235 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
236 },
237 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300238 .fourcc = V4L2_PIX_FMT_NV16,
239 .depth = 16,
240 .colplanes = 2,
241 .h_align = 1,
242 .v_align = 0,
243 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
244 SJPEG_FMT_FLAG_DEC_CAPTURE |
245 SJPEG_FMT_FLAG_EXYNOS4 |
246 SJPEG_FMT_NON_RGB,
247 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
248 },
249 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300250 .fourcc = V4L2_PIX_FMT_NV12,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300251 .depth = 12,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300252 .colplanes = 2,
253 .h_align = 1,
254 .v_align = 1,
255 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
256 SJPEG_FMT_FLAG_DEC_CAPTURE |
257 SJPEG_FMT_FLAG_EXYNOS4 |
258 SJPEG_FMT_NON_RGB,
259 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
260 },
261 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300262 .fourcc = V4L2_PIX_FMT_NV12,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300263 .depth = 12,
264 .colplanes = 2,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300265 .h_align = 3,
266 .v_align = 3,
267 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
268 SJPEG_FMT_FLAG_DEC_CAPTURE |
269 SJPEG_FMT_FLAG_EXYNOS3250 |
270 SJPEG_FMT_NON_RGB,
271 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
272 },
273 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300274 .fourcc = V4L2_PIX_FMT_NV12,
275 .depth = 12,
276 .colplanes = 2,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300277 .h_align = 4,
Jacek Anaszewskia62cffe2014-01-16 08:26:33 -0300278 .v_align = 4,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300279 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
280 SJPEG_FMT_FLAG_DEC_CAPTURE |
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300281 SJPEG_FMT_FLAG_S5P |
282 SJPEG_FMT_NON_RGB,
283 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
284 },
285 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300286 .fourcc = V4L2_PIX_FMT_NV21,
287 .depth = 12,
288 .colplanes = 2,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300289 .h_align = 3,
290 .v_align = 3,
291 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
292 SJPEG_FMT_FLAG_DEC_CAPTURE |
293 SJPEG_FMT_FLAG_EXYNOS3250 |
294 SJPEG_FMT_NON_RGB,
295 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
296 },
297 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300298 .fourcc = V4L2_PIX_FMT_NV21,
299 .depth = 12,
300 .colplanes = 2,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300301 .h_align = 1,
302 .v_align = 1,
303 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
304 SJPEG_FMT_FLAG_DEC_CAPTURE |
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300305 SJPEG_FMT_FLAG_EXYNOS3250 |
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300306 SJPEG_FMT_FLAG_EXYNOS4 |
307 SJPEG_FMT_NON_RGB,
308 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
309 },
310 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300311 .fourcc = V4L2_PIX_FMT_YUV420,
312 .depth = 12,
313 .colplanes = 3,
314 .h_align = 1,
315 .v_align = 1,
316 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
317 SJPEG_FMT_FLAG_DEC_CAPTURE |
318 SJPEG_FMT_FLAG_EXYNOS4 |
319 SJPEG_FMT_NON_RGB,
320 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
321 },
322 {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300323 .fourcc = V4L2_PIX_FMT_YUV420,
324 .depth = 12,
325 .colplanes = 3,
326 .h_align = 4,
327 .v_align = 4,
328 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
329 SJPEG_FMT_FLAG_DEC_CAPTURE |
330 SJPEG_FMT_FLAG_EXYNOS3250 |
331 SJPEG_FMT_NON_RGB,
332 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
333 },
334 {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300335 .fourcc = V4L2_PIX_FMT_GREY,
336 .depth = 8,
337 .colplanes = 1,
338 .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
339 SJPEG_FMT_FLAG_DEC_CAPTURE |
340 SJPEG_FMT_FLAG_EXYNOS4 |
341 SJPEG_FMT_NON_RGB,
342 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300343 },
344};
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300345#define SJPEG_NUM_FORMATS ARRAY_SIZE(sjpeg_formats)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300346
347static const unsigned char qtbl_luminance[4][64] = {
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300348 {/*level 0 - high compression quality */
349 20, 16, 25, 39, 50, 46, 62, 68,
350 16, 18, 23, 38, 38, 53, 65, 68,
351 25, 23, 31, 38, 53, 65, 68, 68,
352 39, 38, 38, 53, 65, 68, 68, 68,
353 50, 38, 53, 65, 68, 68, 68, 68,
354 46, 53, 65, 68, 68, 68, 68, 68,
355 62, 65, 68, 68, 68, 68, 68, 68,
356 68, 68, 68, 68, 68, 68, 68, 68
357 },
358 {/* level 1 */
359 16, 11, 11, 16, 23, 27, 31, 30,
360 11, 12, 12, 15, 20, 23, 23, 30,
361 11, 12, 13, 16, 23, 26, 35, 47,
362 16, 15, 16, 23, 26, 37, 47, 64,
363 23, 20, 23, 26, 39, 51, 64, 64,
364 27, 23, 26, 37, 51, 64, 64, 64,
365 31, 23, 35, 47, 64, 64, 64, 64,
366 30, 30, 47, 64, 64, 64, 64, 64
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300367 },
368 {/* level 2 */
369 12, 8, 8, 12, 17, 21, 24, 23,
370 8, 9, 9, 11, 15, 19, 18, 23,
371 8, 9, 10, 12, 19, 20, 27, 36,
372 12, 11, 12, 21, 20, 28, 36, 53,
373 17, 15, 19, 20, 30, 39, 51, 59,
374 21, 19, 20, 28, 39, 51, 59, 59,
375 24, 18, 27, 36, 51, 59, 59, 59,
376 23, 23, 36, 53, 59, 59, 59, 59
377 },
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300378 {/* level 3 - low compression quality */
379 8, 6, 6, 8, 12, 14, 16, 17,
380 6, 6, 6, 8, 10, 13, 12, 15,
381 6, 6, 7, 8, 13, 14, 18, 24,
382 8, 8, 8, 14, 13, 19, 24, 35,
383 12, 10, 13, 13, 20, 26, 34, 39,
384 14, 13, 14, 19, 26, 34, 39, 39,
385 16, 12, 18, 24, 34, 39, 39, 39,
386 17, 15, 24, 35, 39, 39, 39, 39
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300387 }
388};
389
390static const unsigned char qtbl_chrominance[4][64] = {
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300391 {/*level 0 - high compression quality */
392 21, 25, 32, 38, 54, 68, 68, 68,
393 25, 28, 24, 38, 54, 68, 68, 68,
394 32, 24, 32, 43, 66, 68, 68, 68,
395 38, 38, 43, 53, 68, 68, 68, 68,
396 54, 54, 66, 68, 68, 68, 68, 68,
397 68, 68, 68, 68, 68, 68, 68, 68,
398 68, 68, 68, 68, 68, 68, 68, 68,
399 68, 68, 68, 68, 68, 68, 68, 68
400 },
401 {/* level 1 */
402 17, 15, 17, 21, 20, 26, 38, 48,
403 15, 19, 18, 17, 20, 26, 35, 43,
404 17, 18, 20, 22, 26, 30, 46, 53,
405 21, 17, 22, 28, 30, 39, 53, 64,
406 20, 20, 26, 30, 39, 48, 64, 64,
407 26, 26, 30, 39, 48, 63, 64, 64,
408 38, 35, 46, 53, 64, 64, 64, 64,
409 48, 43, 53, 64, 64, 64, 64, 64
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300410 },
411 {/* level 2 */
412 13, 11, 13, 16, 20, 20, 29, 37,
413 11, 14, 14, 14, 16, 20, 26, 32,
414 13, 14, 15, 17, 20, 23, 35, 40,
415 16, 14, 17, 21, 23, 30, 40, 50,
416 20, 16, 20, 23, 30, 37, 50, 59,
417 20, 20, 23, 30, 37, 48, 59, 59,
418 29, 26, 35, 40, 50, 59, 59, 59,
419 37, 32, 40, 50, 59, 59, 59, 59
420 },
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -0300421 {/* level 3 - low compression quality */
422 9, 8, 9, 11, 14, 17, 19, 24,
423 8, 10, 9, 11, 14, 13, 17, 22,
424 9, 9, 13, 14, 13, 15, 23, 26,
425 11, 11, 14, 14, 15, 20, 26, 33,
426 14, 14, 13, 15, 20, 24, 33, 39,
427 17, 13, 15, 20, 24, 32, 39, 39,
428 19, 17, 23, 26, 33, 39, 39, 39,
429 24, 22, 26, 33, 39, 39, 39, 39
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300430 }
431};
432
433static const unsigned char hdctbl0[16] = {
434 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
435};
436
437static const unsigned char hdctblg0[12] = {
438 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
439};
440static const unsigned char hactbl0[16] = {
441 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
442};
443static const unsigned char hactblg0[162] = {
444 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
445 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
446 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
447 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
448 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
449 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
450 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
451 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
452 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
453 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
454 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
455 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
456 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
457 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
458 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
459 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
460 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
461 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
462 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
463 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
464 0xf9, 0xfa
465};
466
Jacek Anaszewski337777a2013-11-22 06:13:34 -0300467/*
468 * Fourcc downgrade schema lookup tables for 422 and 420
469 * chroma subsampling - fourcc on each position maps on the
470 * fourcc from the table fourcc_to_dwngrd_schema_id which allows
471 * to get the most suitable fourcc counterpart for the given
472 * downgraded subsampling property.
473 */
474static const u32 subs422_fourcc_dwngrd_schema[] = {
475 V4L2_PIX_FMT_NV16,
476 V4L2_PIX_FMT_NV61,
477};
478
479static const u32 subs420_fourcc_dwngrd_schema[] = {
480 V4L2_PIX_FMT_NV12,
481 V4L2_PIX_FMT_NV21,
482 V4L2_PIX_FMT_NV12,
483 V4L2_PIX_FMT_NV21,
484 V4L2_PIX_FMT_NV12,
485 V4L2_PIX_FMT_NV21,
486 V4L2_PIX_FMT_GREY,
487 V4L2_PIX_FMT_GREY,
488 V4L2_PIX_FMT_GREY,
489 V4L2_PIX_FMT_GREY,
490};
491
492/*
493 * Lookup table for translation of a fourcc to the position
494 * of its downgraded counterpart in the *fourcc_dwngrd_schema
495 * tables.
496 */
497static const u32 fourcc_to_dwngrd_schema_id[] = {
498 V4L2_PIX_FMT_NV24,
499 V4L2_PIX_FMT_NV42,
500 V4L2_PIX_FMT_NV16,
501 V4L2_PIX_FMT_NV61,
502 V4L2_PIX_FMT_YUYV,
503 V4L2_PIX_FMT_YVYU,
504 V4L2_PIX_FMT_NV12,
505 V4L2_PIX_FMT_NV21,
506 V4L2_PIX_FMT_YUV420,
507 V4L2_PIX_FMT_GREY,
508};
509
510static int s5p_jpeg_get_dwngrd_sch_id_by_fourcc(u32 fourcc)
511{
512 int i;
Shuah Khan605b8922016-07-14 17:01:56 -0300513
Jacek Anaszewski337777a2013-11-22 06:13:34 -0300514 for (i = 0; i < ARRAY_SIZE(fourcc_to_dwngrd_schema_id); ++i) {
515 if (fourcc_to_dwngrd_schema_id[i] == fourcc)
516 return i;
517 }
518
519 return -EINVAL;
520}
521
522static int s5p_jpeg_adjust_fourcc_to_subsampling(
523 enum v4l2_jpeg_chroma_subsampling subs,
524 u32 in_fourcc,
525 u32 *out_fourcc,
526 struct s5p_jpeg_ctx *ctx)
527{
528 int dwngrd_sch_id;
529
530 if (ctx->subsampling != V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
531 dwngrd_sch_id =
532 s5p_jpeg_get_dwngrd_sch_id_by_fourcc(in_fourcc);
533 if (dwngrd_sch_id < 0)
534 return -EINVAL;
535 }
536
537 switch (ctx->subsampling) {
538 case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
539 *out_fourcc = V4L2_PIX_FMT_GREY;
540 break;
541 case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
542 if (dwngrd_sch_id >
543 ARRAY_SIZE(subs420_fourcc_dwngrd_schema) - 1)
544 return -EINVAL;
545 *out_fourcc = subs420_fourcc_dwngrd_schema[dwngrd_sch_id];
546 break;
547 case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
548 if (dwngrd_sch_id >
549 ARRAY_SIZE(subs422_fourcc_dwngrd_schema) - 1)
550 return -EINVAL;
551 *out_fourcc = subs422_fourcc_dwngrd_schema[dwngrd_sch_id];
552 break;
553 default:
554 *out_fourcc = V4L2_PIX_FMT_GREY;
555 break;
556 }
557
558 return 0;
559}
560
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300561static int exynos4x12_decoded_subsampling[] = {
562 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
563 V4L2_JPEG_CHROMA_SUBSAMPLING_444,
564 V4L2_JPEG_CHROMA_SUBSAMPLING_422,
565 V4L2_JPEG_CHROMA_SUBSAMPLING_420,
566};
567
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300568static int exynos3250_decoded_subsampling[] = {
569 V4L2_JPEG_CHROMA_SUBSAMPLING_444,
570 V4L2_JPEG_CHROMA_SUBSAMPLING_422,
571 V4L2_JPEG_CHROMA_SUBSAMPLING_420,
572 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
573 -1,
574 -1,
575 V4L2_JPEG_CHROMA_SUBSAMPLING_411,
576};
577
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300578static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
579{
580 return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
581}
582
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300583static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh)
584{
585 return container_of(fh, struct s5p_jpeg_ctx, fh);
586}
587
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300588static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
589{
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300590 switch (ctx->jpeg->variant->version) {
591 case SJPEG_S5P:
Tony K Nadackalfa3cb902017-06-30 10:15:41 -0400592 WARN_ON(ctx->subsampling > 3);
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300593 if (ctx->subsampling > 2)
594 return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
595 return ctx->subsampling;
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300596 case SJPEG_EXYNOS3250:
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -0300597 case SJPEG_EXYNOS5420:
Tony K Nadackalfa3cb902017-06-30 10:15:41 -0400598 WARN_ON(ctx->subsampling > 6);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300599 if (ctx->subsampling > 3)
600 return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
601 return exynos3250_decoded_subsampling[ctx->subsampling];
602 case SJPEG_EXYNOS4:
Tony K Nadackalfa3cb902017-06-30 10:15:41 -0400603 WARN_ON(ctx->subsampling > 3);
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300604 if (ctx->subsampling > 2)
605 return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
606 return exynos4x12_decoded_subsampling[ctx->subsampling];
Andrzej Pietrasiewicz4d7be602017-08-08 07:27:08 -0400607 case SJPEG_EXYNOS5433:
608 return ctx->subsampling; /* parsed from header */
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300609 default:
Tony K Nadackalfa3cb902017-06-30 10:15:41 -0400610 WARN_ON(ctx->subsampling > 3);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300611 return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
Jacek Anaszewski303b0a92013-12-18 11:14:00 -0300612 }
613}
614
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300615static inline void s5p_jpeg_set_qtbl(void __iomem *regs,
616 const unsigned char *qtbl,
617 unsigned long tab, int len)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300618{
619 int i;
620
621 for (i = 0; i < len; i++)
622 writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
623}
624
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300625static inline void s5p_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300626{
627 /* this driver fills quantisation table 0 with data for luma */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300628 s5p_jpeg_set_qtbl(regs, qtbl_luminance[quality],
629 S5P_JPG_QTBL_CONTENT(0),
630 ARRAY_SIZE(qtbl_luminance[quality]));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300631}
632
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300633static inline void s5p_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300634{
635 /* this driver fills quantisation table 1 with data for chroma */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300636 s5p_jpeg_set_qtbl(regs, qtbl_chrominance[quality],
637 S5P_JPG_QTBL_CONTENT(1),
638 ARRAY_SIZE(qtbl_chrominance[quality]));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300639}
640
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300641static inline void s5p_jpeg_set_htbl(void __iomem *regs,
642 const unsigned char *htbl,
643 unsigned long tab, int len)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300644{
645 int i;
646
647 for (i = 0; i < len; i++)
648 writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
649}
650
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300651static inline void s5p_jpeg_set_hdctbl(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300652{
653 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300654 s5p_jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0),
655 ARRAY_SIZE(hdctbl0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300656}
657
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300658static inline void s5p_jpeg_set_hdctblg(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300659{
660 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300661 s5p_jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0),
662 ARRAY_SIZE(hdctblg0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300663}
664
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300665static inline void s5p_jpeg_set_hactbl(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300666{
667 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300668 s5p_jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0),
669 ARRAY_SIZE(hactbl0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300670}
671
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300672static inline void s5p_jpeg_set_hactblg(void __iomem *regs)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300673{
674 /* this driver fills table 0 for this component */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -0300675 s5p_jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0),
676 ARRAY_SIZE(hactblg0));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300677}
678
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300679static inline void exynos4_jpeg_set_tbl(void __iomem *regs,
680 const unsigned char *tbl,
681 unsigned long tab, int len)
682{
683 int i;
684 unsigned int dword;
685
686 for (i = 0; i < len; i += 4) {
687 dword = tbl[i] |
688 (tbl[i + 1] << 8) |
689 (tbl[i + 2] << 16) |
690 (tbl[i + 3] << 24);
691 writel(dword, regs + tab + i);
692 }
693}
694
695static inline void exynos4_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
696{
697 /* this driver fills quantisation table 0 with data for luma */
698 exynos4_jpeg_set_tbl(regs, qtbl_luminance[quality],
699 EXYNOS4_QTBL_CONTENT(0),
700 ARRAY_SIZE(qtbl_luminance[quality]));
701}
702
703static inline void exynos4_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
704{
705 /* this driver fills quantisation table 1 with data for chroma */
706 exynos4_jpeg_set_tbl(regs, qtbl_chrominance[quality],
707 EXYNOS4_QTBL_CONTENT(1),
708 ARRAY_SIZE(qtbl_chrominance[quality]));
709}
710
Mauro Carvalho Chehabaf425be2014-08-26 10:50:23 -0300711static void exynos4_jpeg_set_huff_tbl(void __iomem *base)
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300712{
713 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCLL,
714 ARRAY_SIZE(hdctbl0));
715 exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCCL,
716 ARRAY_SIZE(hdctbl0));
717 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCLV,
718 ARRAY_SIZE(hdctblg0));
719 exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCCV,
720 ARRAY_SIZE(hdctblg0));
721 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACLL,
722 ARRAY_SIZE(hactbl0));
723 exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACCL,
724 ARRAY_SIZE(hactbl0));
725 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACLV,
726 ARRAY_SIZE(hactblg0));
727 exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV,
728 ARRAY_SIZE(hactblg0));
729}
730
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300731static inline int __exynos4_huff_tbl(int class, int id, bool lenval)
732{
733 /*
734 * class: 0 - DC, 1 - AC
735 * id: 0 - Y, 1 - Cb/Cr
736 */
737 if (class) {
738 if (id)
739 return lenval ? EXYNOS4_HUFF_TBL_HACCL :
740 EXYNOS4_HUFF_TBL_HACCV;
741 return lenval ? EXYNOS4_HUFF_TBL_HACLL : EXYNOS4_HUFF_TBL_HACLV;
742
743 }
744 /* class == 0 */
745 if (id)
746 return lenval ? EXYNOS4_HUFF_TBL_HDCCL : EXYNOS4_HUFF_TBL_HDCCV;
747
748 return lenval ? EXYNOS4_HUFF_TBL_HDCLL : EXYNOS4_HUFF_TBL_HDCLV;
749}
750
751static inline int exynos4_huff_tbl_len(int class, int id)
752{
753 return __exynos4_huff_tbl(class, id, true);
754}
755
756static inline int exynos4_huff_tbl_val(int class, int id)
757{
758 return __exynos4_huff_tbl(class, id, false);
759}
760
761static int get_byte(struct s5p_jpeg_buffer *buf);
762static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word);
763static void skip(struct s5p_jpeg_buffer *buf, long len);
764
765static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx)
766{
767 struct s5p_jpeg *jpeg = ctx->jpeg;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -0500768 struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300769 struct s5p_jpeg_buffer jpeg_buffer;
770 unsigned int word;
771 int c, x, components;
772
773 jpeg_buffer.size = 2; /* Ls */
774 jpeg_buffer.data =
Ezequiel Garcia4a88f892019-02-08 11:17:45 -0500775 (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sos + 2;
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300776 jpeg_buffer.curr = 0;
777
778 word = 0;
779
780 if (get_word_be(&jpeg_buffer, &word))
781 return;
782 jpeg_buffer.size = (long)word - 2;
783 jpeg_buffer.data += 2;
784 jpeg_buffer.curr = 0;
785
786 components = get_byte(&jpeg_buffer);
787 if (components == -1)
788 return;
789 while (components--) {
790 c = get_byte(&jpeg_buffer);
791 if (c == -1)
792 return;
793 x = get_byte(&jpeg_buffer);
794 if (x == -1)
795 return;
796 exynos4_jpeg_select_dec_h_tbl(jpeg->regs, c,
797 (((x >> 4) & 0x1) << 1) | (x & 0x1));
798 }
799
800}
801
802static void exynos4_jpeg_parse_huff_tbl(struct s5p_jpeg_ctx *ctx)
803{
804 struct s5p_jpeg *jpeg = ctx->jpeg;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -0500805 struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300806 struct s5p_jpeg_buffer jpeg_buffer;
807 unsigned int word;
808 int c, i, n, j;
809
810 for (j = 0; j < ctx->out_q.dht.n; ++j) {
811 jpeg_buffer.size = ctx->out_q.dht.len[j];
Ezequiel Garcia4a88f892019-02-08 11:17:45 -0500812 jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) +
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300813 ctx->out_q.dht.marker[j];
814 jpeg_buffer.curr = 0;
815
816 word = 0;
817 while (jpeg_buffer.curr < jpeg_buffer.size) {
818 char id, class;
819
820 c = get_byte(&jpeg_buffer);
821 if (c == -1)
822 return;
823 id = c & 0xf;
824 class = (c >> 4) & 0xf;
825 n = 0;
826 for (i = 0; i < 16; ++i) {
827 c = get_byte(&jpeg_buffer);
828 if (c == -1)
829 return;
830 word |= c << ((i % 4) * 8);
831 if ((i + 1) % 4 == 0) {
832 writel(word, jpeg->regs +
833 exynos4_huff_tbl_len(class, id) +
834 (i / 4) * 4);
835 word = 0;
836 }
837 n += c;
838 }
839 word = 0;
840 for (i = 0; i < n; ++i) {
841 c = get_byte(&jpeg_buffer);
842 if (c == -1)
843 return;
844 word |= c << ((i % 4) * 8);
845 if ((i + 1) % 4 == 0) {
846 writel(word, jpeg->regs +
847 exynos4_huff_tbl_val(class, id) +
848 (i / 4) * 4);
849 word = 0;
850 }
851 }
852 if (i % 4) {
853 writel(word, jpeg->regs +
854 exynos4_huff_tbl_val(class, id) + (i / 4) * 4);
855 }
856 word = 0;
857 }
858 }
859}
860
861static void exynos4_jpeg_parse_decode_q_tbl(struct s5p_jpeg_ctx *ctx)
862{
863 struct s5p_jpeg *jpeg = ctx->jpeg;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -0500864 struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300865 struct s5p_jpeg_buffer jpeg_buffer;
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300866 int c, x, components;
867
868 jpeg_buffer.size = ctx->out_q.sof_len;
869 jpeg_buffer.data =
Ezequiel Garcia4a88f892019-02-08 11:17:45 -0500870 (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sof;
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300871 jpeg_buffer.curr = 0;
872
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300873 skip(&jpeg_buffer, 5); /* P, Y, X */
874 components = get_byte(&jpeg_buffer);
875 if (components == -1)
876 return;
877
878 exynos4_jpeg_set_dec_components(jpeg->regs, components);
879
880 while (components--) {
881 c = get_byte(&jpeg_buffer);
882 if (c == -1)
883 return;
884 skip(&jpeg_buffer, 1);
885 x = get_byte(&jpeg_buffer);
886 if (x == -1)
887 return;
888 exynos4_jpeg_select_dec_q_tbl(jpeg->regs, c, x);
889 }
890}
891
892static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx)
893{
894 struct s5p_jpeg *jpeg = ctx->jpeg;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -0500895 struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300896 struct s5p_jpeg_buffer jpeg_buffer;
897 unsigned int word;
898 int c, i, j;
899
900 for (j = 0; j < ctx->out_q.dqt.n; ++j) {
901 jpeg_buffer.size = ctx->out_q.dqt.len[j];
Ezequiel Garcia4a88f892019-02-08 11:17:45 -0500902 jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) +
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -0300903 ctx->out_q.dqt.marker[j];
904 jpeg_buffer.curr = 0;
905
906 word = 0;
907 while (jpeg_buffer.size - jpeg_buffer.curr >= 65) {
908 char id;
909
910 c = get_byte(&jpeg_buffer);
911 if (c == -1)
912 return;
913 id = c & 0xf;
914 /* nonzero means extended mode - not supported */
915 if ((c >> 4) & 0xf)
916 return;
917 for (i = 0; i < 64; ++i) {
918 c = get_byte(&jpeg_buffer);
919 if (c == -1)
920 return;
921 word |= c << ((i % 4) * 8);
922 if ((i + 1) % 4 == 0) {
923 writel(word, jpeg->regs +
924 EXYNOS4_QTBL_CONTENT(id) + (i / 4) * 4);
925 word = 0;
926 }
927 }
928 word = 0;
929 }
930 }
931}
932
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300933/*
934 * ============================================================================
935 * Device file operations
936 * ============================================================================
937 */
938
939static int queue_init(void *priv, struct vb2_queue *src_vq,
940 struct vb2_queue *dst_vq);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300941static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
942 __u32 pixelformat, unsigned int fmt_type);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300943static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300944
945static int s5p_jpeg_open(struct file *file)
946{
947 struct s5p_jpeg *jpeg = video_drvdata(file);
948 struct video_device *vfd = video_devdata(file);
949 struct s5p_jpeg_ctx *ctx;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300950 struct s5p_jpeg_fmt *out_fmt, *cap_fmt;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300951 int ret = 0;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300952
Sachin Kamatb5146c92012-08-16 08:52:58 -0300953 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300954 if (!ctx)
955 return -ENOMEM;
956
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300957 if (mutex_lock_interruptible(&jpeg->lock)) {
958 ret = -ERESTARTSYS;
959 goto free;
960 }
961
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300962 v4l2_fh_init(&ctx->fh, vfd);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -0300963 /* Use separate control handler per file handle */
964 ctx->fh.ctrl_handler = &ctx->ctrl_handler;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300965 file->private_data = &ctx->fh;
966 v4l2_fh_add(&ctx->fh);
967
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300968 ctx->jpeg = jpeg;
969 if (vfd == jpeg->vfd_encoder) {
970 ctx->mode = S5P_JPEG_ENCODE;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300971 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_RGB565,
972 FMT_TYPE_OUTPUT);
973 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
974 FMT_TYPE_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300975 } else {
976 ctx->mode = S5P_JPEG_DECODE;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300977 out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
978 FMT_TYPE_OUTPUT);
979 cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
980 FMT_TYPE_CAPTURE);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -0300981 ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300982 }
983
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -0300984 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
985 if (IS_ERR(ctx->fh.m2m_ctx)) {
986 ret = PTR_ERR(ctx->fh.m2m_ctx);
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300987 goto error;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300988 }
989
990 ctx->out_q.fmt = out_fmt;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -0300991 ctx->cap_q.fmt = cap_fmt;
992
993 ret = s5p_jpeg_controls_create(ctx);
994 if (ret < 0)
995 goto error;
996
Hans Verkuilb0d5cd62012-06-24 06:54:18 -0300997 mutex_unlock(&jpeg->lock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -0300998 return 0;
Sylwester Nawrocki275de242012-02-17 11:38:09 -0300999
1000error:
1001 v4l2_fh_del(&ctx->fh);
1002 v4l2_fh_exit(&ctx->fh);
Hans Verkuilb0d5cd62012-06-24 06:54:18 -03001003 mutex_unlock(&jpeg->lock);
1004free:
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001005 kfree(ctx);
1006 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001007}
1008
1009static int s5p_jpeg_release(struct file *file)
1010{
Hans Verkuilb0d5cd62012-06-24 06:54:18 -03001011 struct s5p_jpeg *jpeg = video_drvdata(file);
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001012 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001013
Hans Verkuilb0d5cd62012-06-24 06:54:18 -03001014 mutex_lock(&jpeg->lock);
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001015 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001016 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001017 v4l2_fh_del(&ctx->fh);
1018 v4l2_fh_exit(&ctx->fh);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001019 kfree(ctx);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001020 mutex_unlock(&jpeg->lock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001021
1022 return 0;
1023}
1024
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001025static const struct v4l2_file_operations s5p_jpeg_fops = {
1026 .owner = THIS_MODULE,
1027 .open = s5p_jpeg_open,
1028 .release = s5p_jpeg_release,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001029 .poll = v4l2_m2m_fop_poll,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001030 .unlocked_ioctl = video_ioctl2,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001031 .mmap = v4l2_m2m_fop_mmap,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001032};
1033
1034/*
1035 * ============================================================================
1036 * video ioctl operations
1037 * ============================================================================
1038 */
1039
1040static int get_byte(struct s5p_jpeg_buffer *buf)
1041{
1042 if (buf->curr >= buf->size)
1043 return -1;
1044
1045 return ((unsigned char *)buf->data)[buf->curr++];
1046}
1047
1048static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
1049{
1050 unsigned int temp;
1051 int byte;
1052
1053 byte = get_byte(buf);
1054 if (byte == -1)
1055 return -1;
1056 temp = byte << 8;
1057 byte = get_byte(buf);
1058 if (byte == -1)
1059 return -1;
1060 *word = (unsigned int)byte | temp;
1061 return 0;
1062}
1063
1064static void skip(struct s5p_jpeg_buffer *buf, long len)
1065{
1066 if (len <= 0)
1067 return;
1068
1069 while (len--)
1070 get_byte(buf);
1071}
1072
Thierry Escandec8d36a82017-06-30 10:15:44 -04001073static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx,
1074 unsigned int subsampling)
1075{
Tony K Nadackalaccf9b22017-06-30 10:15:45 -04001076 unsigned int version;
1077
Thierry Escandec8d36a82017-06-30 10:15:44 -04001078 switch (subsampling) {
1079 case 0x11:
1080 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444;
1081 break;
1082 case 0x21:
1083 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422;
1084 break;
1085 case 0x22:
1086 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420;
1087 break;
1088 case 0x33:
1089 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
1090 break;
Tony K Nadackalaccf9b22017-06-30 10:15:45 -04001091 case 0x41:
1092 /*
1093 * 4:1:1 subsampling only supported by 3250, 5420, and 5433
1094 * variants
1095 */
1096 version = ctx->jpeg->variant->version;
1097 if (version != SJPEG_EXYNOS3250 &&
1098 version != SJPEG_EXYNOS5420 &&
1099 version != SJPEG_EXYNOS5433)
1100 return false;
1101
1102 ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_411;
1103 break;
Thierry Escandec8d36a82017-06-30 10:15:44 -04001104 default:
1105 return false;
1106 }
1107
1108 return true;
1109}
1110
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001111static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
Jacek Anaszewskif8433962013-11-21 13:33:09 -03001112 unsigned long buffer, unsigned long size,
1113 struct s5p_jpeg_ctx *ctx)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001114{
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03001115 int c, components = 0, notfound, n_dht = 0, n_dqt = 0;
Mauro Carvalho Chehaba16e3772017-05-18 10:40:00 -03001116 unsigned int height = 0, width = 0, word, subsampling = 0;
1117 unsigned int sos = 0, sof = 0, sof_len = 0;
1118 unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER];
1119 unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001120 long length;
1121 struct s5p_jpeg_buffer jpeg_buffer;
1122
1123 jpeg_buffer.size = size;
1124 jpeg_buffer.data = buffer;
1125 jpeg_buffer.curr = 0;
1126
1127 notfound = 1;
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03001128 while (notfound || !sos) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001129 c = get_byte(&jpeg_buffer);
1130 if (c == -1)
Jacek Anaszewskia35f6002014-07-11 12:19:43 -03001131 return false;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001132 if (c != 0xff)
1133 continue;
1134 do
1135 c = get_byte(&jpeg_buffer);
1136 while (c == 0xff);
1137 if (c == -1)
Jacek Anaszewskia35f6002014-07-11 12:19:43 -03001138 return false;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001139 if (c == 0)
1140 continue;
1141 length = 0;
1142 switch (c) {
1143 /* SOF0: baseline JPEG */
1144 case SOF0:
1145 if (get_word_be(&jpeg_buffer, &word))
1146 break;
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03001147 length = (long)word - 2;
1148 if (!length)
1149 return false;
1150 sof = jpeg_buffer.curr; /* after 0xffc0 */
1151 sof_len = length;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001152 if (get_byte(&jpeg_buffer) == -1)
1153 break;
1154 if (get_word_be(&jpeg_buffer, &height))
1155 break;
1156 if (get_word_be(&jpeg_buffer, &width))
1157 break;
1158 components = get_byte(&jpeg_buffer);
1159 if (components == -1)
1160 break;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001161
Jacek Anaszewskif8433962013-11-21 13:33:09 -03001162 if (components == 1) {
1163 subsampling = 0x33;
1164 } else {
1165 skip(&jpeg_buffer, 1);
1166 subsampling = get_byte(&jpeg_buffer);
1167 skip(&jpeg_buffer, 1);
1168 }
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03001169 if (components > 3)
1170 return false;
Jacek Anaszewskif8433962013-11-21 13:33:09 -03001171 skip(&jpeg_buffer, components * 2);
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03001172 notfound = 0;
1173 break;
1174
1175 case DQT:
1176 if (get_word_be(&jpeg_buffer, &word))
1177 break;
1178 length = (long)word - 2;
1179 if (!length)
1180 return false;
1181 if (n_dqt >= S5P_JPEG_MAX_MARKER)
1182 return false;
1183 dqt[n_dqt] = jpeg_buffer.curr; /* after 0xffdb */
1184 dqt_len[n_dqt++] = length;
1185 skip(&jpeg_buffer, length);
1186 break;
1187
1188 case DHT:
1189 if (get_word_be(&jpeg_buffer, &word))
1190 break;
1191 length = (long)word - 2;
1192 if (!length)
1193 return false;
1194 if (n_dht >= S5P_JPEG_MAX_MARKER)
1195 return false;
1196 dht[n_dht] = jpeg_buffer.curr; /* after 0xffc4 */
1197 dht_len[n_dht++] = length;
1198 skip(&jpeg_buffer, length);
1199 break;
1200
1201 case SOS:
1202 sos = jpeg_buffer.curr - 2; /* 0xffda */
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001203 break;
1204
1205 /* skip payload-less markers */
1206 case RST ... RST + 7:
1207 case SOI:
1208 case EOI:
1209 case TEM:
1210 break;
1211
1212 /* skip uninteresting payload markers */
1213 default:
1214 if (get_word_be(&jpeg_buffer, &word))
1215 break;
1216 length = (long)word - 2;
1217 skip(&jpeg_buffer, length);
1218 break;
1219 }
1220 }
Thierry Escandefe8a57b2017-06-30 10:15:42 -04001221
Thierry Escandec8d36a82017-06-30 10:15:44 -04001222 if (notfound || !sos || !s5p_jpeg_subsampling_decode(ctx, subsampling))
Thierry Escandefe8a57b2017-06-30 10:15:42 -04001223 return false;
Jacek Anaszewskif8433962013-11-21 13:33:09 -03001224
Thierry Escandefe8a57b2017-06-30 10:15:42 -04001225 result->w = width;
1226 result->h = height;
1227 result->sos = sos;
1228 result->dht.n = n_dht;
1229 while (n_dht--) {
1230 result->dht.marker[n_dht] = dht[n_dht];
1231 result->dht.len[n_dht] = dht_len[n_dht];
1232 }
1233 result->dqt.n = n_dqt;
1234 while (n_dqt--) {
1235 result->dqt.marker[n_dqt] = dqt[n_dqt];
1236 result->dqt.len[n_dqt] = dqt_len[n_dqt];
1237 }
1238 result->sof = sof;
1239 result->sof_len = sof_len;
Thierry Escandefe8a57b2017-06-30 10:15:42 -04001240
1241 return true;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001242}
1243
1244static int s5p_jpeg_querycap(struct file *file, void *priv,
1245 struct v4l2_capability *cap)
1246{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001247 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001248
1249 if (ctx->mode == S5P_JPEG_ENCODE) {
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001250 strscpy(cap->driver, S5P_JPEG_M2M_NAME,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001251 sizeof(cap->driver));
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001252 strscpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001253 sizeof(cap->card));
1254 } else {
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001255 strscpy(cap->driver, S5P_JPEG_M2M_NAME,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001256 sizeof(cap->driver));
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001257 strscpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001258 sizeof(cap->card));
1259 }
Javier Martinez Canillas3b2aa382016-06-16 18:40:32 -03001260 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
1261 dev_name(ctx->jpeg->dev));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001262 return 0;
1263}
1264
Pawe? Chmiel49710c32018-12-29 10:46:01 -05001265static int enum_fmt(struct s5p_jpeg_ctx *ctx,
1266 struct s5p_jpeg_fmt *sjpeg_formats, int n,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001267 struct v4l2_fmtdesc *f, u32 type)
1268{
1269 int i, num = 0;
Pawe? Chmiel49710c32018-12-29 10:46:01 -05001270 unsigned int fmt_ver_flag = ctx->jpeg->variant->fmt_ver_flag;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001271
1272 for (i = 0; i < n; ++i) {
Pawe? Chmiel49710c32018-12-29 10:46:01 -05001273 if (sjpeg_formats[i].flags & type &&
1274 sjpeg_formats[i].flags & fmt_ver_flag) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001275 /* index-th format of type type found ? */
1276 if (num == f->index)
1277 break;
1278 /* Correct type but haven't reached our index yet,
Shuah Khan605b8922016-07-14 17:01:56 -03001279 * just increment per-type index
1280 */
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001281 ++num;
1282 }
1283 }
1284
1285 /* Format not found */
1286 if (i >= n)
1287 return -EINVAL;
1288
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001289 f->pixelformat = sjpeg_formats[i].fourcc;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001290
1291 return 0;
1292}
1293
1294static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
1295 struct v4l2_fmtdesc *f)
1296{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001297 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001298
1299 if (ctx->mode == S5P_JPEG_ENCODE)
Pawe? Chmiel49710c32018-12-29 10:46:01 -05001300 return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001301 SJPEG_FMT_FLAG_ENC_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001302
Pawe? Chmiel49710c32018-12-29 10:46:01 -05001303 return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
1304 SJPEG_FMT_FLAG_DEC_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001305}
1306
1307static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
1308 struct v4l2_fmtdesc *f)
1309{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001310 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001311
1312 if (ctx->mode == S5P_JPEG_ENCODE)
Pawe? Chmiel49710c32018-12-29 10:46:01 -05001313 return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001314 SJPEG_FMT_FLAG_ENC_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001315
Pawe? Chmiel49710c32018-12-29 10:46:01 -05001316 return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
1317 SJPEG_FMT_FLAG_DEC_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001318}
1319
1320static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
1321 enum v4l2_buf_type type)
1322{
1323 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1324 return &ctx->out_q;
1325 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1326 return &ctx->cap_q;
1327
1328 return NULL;
1329}
1330
1331static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
1332{
1333 struct vb2_queue *vq;
1334 struct s5p_jpeg_q_data *q_data = NULL;
1335 struct v4l2_pix_format *pix = &f->fmt.pix;
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001336 struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001337
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001338 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001339 if (!vq)
1340 return -EINVAL;
1341
1342 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1343 ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
1344 return -EINVAL;
1345 q_data = get_q_data(ct, f->type);
1346 BUG_ON(q_data == NULL);
1347
1348 pix->width = q_data->w;
1349 pix->height = q_data->h;
1350 pix->field = V4L2_FIELD_NONE;
1351 pix->pixelformat = q_data->fmt->fourcc;
1352 pix->bytesperline = 0;
1353 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
1354 u32 bpl = q_data->w;
Shuah Khan605b8922016-07-14 17:01:56 -03001355
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001356 if (q_data->fmt->colplanes == 1)
1357 bpl = (bpl * q_data->fmt->depth) >> 3;
1358 pix->bytesperline = bpl;
1359 }
1360 pix->sizeimage = q_data->size;
1361
1362 return 0;
1363}
1364
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001365static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
1366 u32 pixelformat, unsigned int fmt_type)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001367{
Jacek Anaszewskib2451682014-04-10 04:32:11 -03001368 unsigned int k, fmt_flag;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001369
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001370 if (ctx->mode == S5P_JPEG_ENCODE)
1371 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
1372 SJPEG_FMT_FLAG_ENC_OUTPUT :
1373 SJPEG_FMT_FLAG_ENC_CAPTURE;
1374 else
1375 fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
1376 SJPEG_FMT_FLAG_DEC_OUTPUT :
1377 SJPEG_FMT_FLAG_DEC_CAPTURE;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001378
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001379 for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) {
1380 struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k];
Shuah Khan605b8922016-07-14 17:01:56 -03001381
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001382 if (fmt->fourcc == pixelformat &&
1383 fmt->flags & fmt_flag &&
Jacek Anaszewskib2451682014-04-10 04:32:11 -03001384 fmt->flags & ctx->jpeg->variant->fmt_ver_flag) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001385 return fmt;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001386 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001387 }
1388
1389 return NULL;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001390}
1391
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001392static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
1393 u32 *w, unsigned int wmin, unsigned int wmax,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001394 unsigned int walign,
1395 u32 *h, unsigned int hmin, unsigned int hmax,
1396 unsigned int halign)
1397{
1398 int width, height, w_step, h_step;
1399
1400 width = *w;
1401 height = *h;
1402
1403 w_step = 1 << walign;
1404 h_step = 1 << halign;
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001405
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001406 if (ctx->jpeg->variant->hw3250_compat) {
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001407 /*
1408 * Rightmost and bottommost pixels are cropped by the
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001409 * Exynos3250/compatible JPEG IP for RGB formats, for the
1410 * specific width and height values respectively. This
1411 * assignment will result in v4l_bound_align_image returning
1412 * dimensions reduced by 1 for the aforementioned cases.
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001413 */
1414 if (w_step == 4 && ((width & 3) == 1)) {
1415 wmax = width;
1416 hmax = height;
1417 }
1418 }
1419
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001420 v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
1421
1422 if (*w < width && (*w + w_step) < wmax)
1423 *w += w_step;
1424 if (*h < height && (*h + h_step) < hmax)
1425 *h += h_step;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001426}
1427
1428static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
1429 struct s5p_jpeg_ctx *ctx, int q_type)
1430{
1431 struct v4l2_pix_format *pix = &f->fmt.pix;
1432
1433 if (pix->field == V4L2_FIELD_ANY)
1434 pix->field = V4L2_FIELD_NONE;
1435 else if (pix->field != V4L2_FIELD_NONE)
1436 return -EINVAL;
1437
1438 /* V4L2 specification suggests the driver corrects the format struct
Shuah Khan605b8922016-07-14 17:01:56 -03001439 * if any of the dimensions is unsupported
1440 */
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001441 if (q_type == FMT_TYPE_OUTPUT)
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001442 jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001443 S5P_JPEG_MAX_WIDTH, 0,
1444 &pix->height, S5P_JPEG_MIN_HEIGHT,
1445 S5P_JPEG_MAX_HEIGHT, 0);
1446 else
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001447 jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001448 S5P_JPEG_MAX_WIDTH, fmt->h_align,
1449 &pix->height, S5P_JPEG_MIN_HEIGHT,
1450 S5P_JPEG_MAX_HEIGHT, fmt->v_align);
1451
1452 if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
1453 if (pix->sizeimage <= 0)
1454 pix->sizeimage = PAGE_SIZE;
1455 pix->bytesperline = 0;
1456 } else {
1457 u32 bpl = pix->bytesperline;
1458
1459 if (fmt->colplanes > 1 && bpl < pix->width)
1460 bpl = pix->width; /* planar */
1461
1462 if (fmt->colplanes == 1 && /* packed */
Jacek Anaszewskicc690902013-11-25 06:58:10 -03001463 (bpl << 3) / fmt->depth < pix->width)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001464 bpl = (pix->width * fmt->depth) >> 3;
1465
1466 pix->bytesperline = bpl;
1467 pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
1468 }
1469
1470 return 0;
1471}
1472
1473static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
1474 struct v4l2_format *f)
1475{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001476 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001477 struct v4l2_pix_format *pix = &f->fmt.pix;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001478 struct s5p_jpeg_fmt *fmt;
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001479 int ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001480
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001481 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1482 FMT_TYPE_CAPTURE);
1483 if (!fmt) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001484 v4l2_err(&ctx->jpeg->v4l2_dev,
1485 "Fourcc format (0x%08x) invalid.\n",
1486 f->fmt.pix.pixelformat);
1487 return -EINVAL;
1488 }
1489
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03001490 if (!ctx->jpeg->variant->hw_ex4_compat || ctx->mode != S5P_JPEG_DECODE)
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001491 goto exit;
1492
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001493 /*
1494 * The exynos4x12 device requires resulting YUV image
1495 * subsampling not to be lower than the input jpeg subsampling.
1496 * If this requirement is not met then downgrade the requested
1497 * capture format to the one with subsampling equal to the input jpeg.
1498 */
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001499 if ((fmt->flags & SJPEG_FMT_NON_RGB) &&
Jacek Anaszewski337777a2013-11-22 06:13:34 -03001500 (fmt->subsampling < ctx->subsampling)) {
1501 ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
1502 fmt->fourcc,
1503 &pix->pixelformat,
1504 ctx);
1505 if (ret < 0)
1506 pix->pixelformat = V4L2_PIX_FMT_GREY;
1507
1508 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1509 FMT_TYPE_CAPTURE);
1510 }
1511
Jacek Anaszewski2caeeb02014-04-10 04:32:17 -03001512 /*
1513 * Decompression of a JPEG file with 4:2:0 subsampling and odd
1514 * width to the YUV 4:2:0 compliant formats produces a raw image
1515 * with broken luma component. Adjust capture format to RGB565
1516 * in such a case.
1517 */
1518 if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
1519 (ctx->out_q.w & 1) &&
1520 (pix->pixelformat == V4L2_PIX_FMT_NV12 ||
1521 pix->pixelformat == V4L2_PIX_FMT_NV21 ||
1522 pix->pixelformat == V4L2_PIX_FMT_YUV420)) {
1523 pix->pixelformat = V4L2_PIX_FMT_RGB565;
1524 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1525 FMT_TYPE_CAPTURE);
1526 }
1527
1528exit:
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001529 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001530}
1531
1532static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
1533 struct v4l2_format *f)
1534{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001535 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001536 struct s5p_jpeg_fmt *fmt;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001537
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001538 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
1539 FMT_TYPE_OUTPUT);
1540 if (!fmt) {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001541 v4l2_err(&ctx->jpeg->v4l2_dev,
1542 "Fourcc format (0x%08x) invalid.\n",
1543 f->fmt.pix.pixelformat);
1544 return -EINVAL;
1545 }
1546
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001547 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001548}
1549
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001550static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
1551 struct v4l2_format *f,
1552 int fmt_depth)
1553{
1554 struct v4l2_pix_format *pix = &f->fmt.pix;
1555 u32 pix_fmt = f->fmt.pix.pixelformat;
1556 int w = pix->width, h = pix->height, wh_align;
Andrzej Pietrasiewicz77401dd2015-12-08 12:39:08 -02001557 int padding = 0;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001558
1559 if (pix_fmt == V4L2_PIX_FMT_RGB32 ||
Andrzej Pietrasiewicz77401dd2015-12-08 12:39:08 -02001560 pix_fmt == V4L2_PIX_FMT_RGB565 ||
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001561 pix_fmt == V4L2_PIX_FMT_NV24 ||
1562 pix_fmt == V4L2_PIX_FMT_NV42 ||
1563 pix_fmt == V4L2_PIX_FMT_NV12 ||
1564 pix_fmt == V4L2_PIX_FMT_NV21 ||
1565 pix_fmt == V4L2_PIX_FMT_YUV420)
1566 wh_align = 4;
1567 else
1568 wh_align = 1;
1569
Jacek Anaszewskie9e7dfe2014-07-11 12:19:44 -03001570 jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH,
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001571 S5P_JPEG_MAX_WIDTH, wh_align,
1572 &h, S5P_JPEG_MIN_HEIGHT,
1573 S5P_JPEG_MAX_HEIGHT, wh_align);
1574
Andrzej Pietrasiewicz77401dd2015-12-08 12:39:08 -02001575 if (ctx->jpeg->variant->version == SJPEG_EXYNOS4)
1576 padding = PAGE_SIZE;
1577
1578 return (w * h * fmt_depth >> 3) + padding;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001579}
1580
Jacek Anaszewski5a716712014-07-11 12:19:47 -03001581static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
1582 struct v4l2_rect *r);
1583
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001584static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
1585{
1586 struct vb2_queue *vq;
1587 struct s5p_jpeg_q_data *q_data = NULL;
1588 struct v4l2_pix_format *pix = &f->fmt.pix;
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001589 struct v4l2_ctrl *ctrl_subs;
Jacek Anaszewski5a716712014-07-11 12:19:47 -03001590 struct v4l2_rect scale_rect;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001591 unsigned int f_type;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001592
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03001593 vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001594 if (!vq)
1595 return -EINVAL;
1596
1597 q_data = get_q_data(ct, f->type);
1598 BUG_ON(q_data == NULL);
1599
1600 if (vb2_is_busy(vq)) {
1601 v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
1602 return -EBUSY;
1603 }
1604
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03001605 f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
1606 FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;
1607
1608 q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);
Andrzej Pietrasiewicz19dc3e02017-08-11 07:50:01 -04001609 if (ct->mode == S5P_JPEG_ENCODE ||
1610 (ct->mode == S5P_JPEG_DECODE &&
1611 q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG)) {
1612 q_data->w = pix->width;
1613 q_data->h = pix->height;
1614 }
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001615 if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
1616 /*
1617 * During encoding Exynos4x12 SoCs access wider memory area
1618 * than it results from Image_x and Image_y values written to
1619 * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu
1620 * page fault calculate proper buffer size in such a case.
1621 */
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03001622 if (ct->jpeg->variant->hw_ex4_compat &&
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001623 f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)
1624 q_data->size = exynos4_jpeg_get_output_buffer_size(ct,
1625 f,
1626 q_data->fmt->depth);
1627 else
1628 q_data->size = q_data->w * q_data->h *
1629 q_data->fmt->depth >> 3;
1630 } else {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001631 q_data->size = pix->sizeimage;
Jacek Anaszewskib2254d62014-04-10 04:32:16 -03001632 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001633
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001634 if (f_type == FMT_TYPE_OUTPUT) {
1635 ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler,
1636 V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
1637 if (ctrl_subs)
1638 v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
Jacek Anaszewskidfd96902014-07-11 12:19:46 -03001639 ct->crop_altered = false;
1640 }
1641
1642 /*
1643 * For decoding init crop_rect with capture buffer dimmensions which
1644 * contain aligned dimensions of the input JPEG image and do it only
1645 * if crop rectangle hasn't been altered by the user space e.g. with
1646 * S_SELECTION ioctl. For encoding assign output buffer dimensions.
1647 */
1648 if (!ct->crop_altered &&
1649 ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) ||
1650 (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) {
1651 ct->crop_rect.width = pix->width;
1652 ct->crop_rect.height = pix->height;
1653 }
Jacek Anaszewski5a716712014-07-11 12:19:47 -03001654
1655 /*
1656 * Prevent downscaling to YUV420 format by more than 2
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001657 * for Exynos3250/compatible SoC as it produces broken raw image
Jacek Anaszewski5a716712014-07-11 12:19:47 -03001658 * in such cases.
1659 */
1660 if (ct->mode == S5P_JPEG_DECODE &&
1661 f_type == FMT_TYPE_CAPTURE &&
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001662 ct->jpeg->variant->hw3250_compat &&
Jacek Anaszewski5a716712014-07-11 12:19:47 -03001663 pix->pixelformat == V4L2_PIX_FMT_YUV420 &&
1664 ct->scale_factor > 2) {
1665 scale_rect.width = ct->out_q.w / 2;
1666 scale_rect.height = ct->out_q.h / 2;
1667 exynos3250_jpeg_try_downscale(ct, &scale_rect);
Jacek Anaszewski4a30d302013-11-21 13:33:52 -03001668 }
1669
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001670 return 0;
1671}
1672
1673static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
1674 struct v4l2_format *f)
1675{
1676 int ret;
1677
1678 ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
1679 if (ret)
1680 return ret;
1681
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001682 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001683}
1684
1685static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
1686 struct v4l2_format *f)
1687{
1688 int ret;
1689
1690 ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
1691 if (ret)
1692 return ret;
1693
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001694 return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001695}
1696
henryhsu1c84e7f2017-06-30 10:15:46 -04001697static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh,
1698 const struct v4l2_event_subscription *sub)
1699{
1700 if (sub->type == V4L2_EVENT_SOURCE_CHANGE)
1701 return v4l2_src_change_event_subscribe(fh, sub);
1702
1703 return -EINVAL;
1704}
1705
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001706static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
1707 struct v4l2_rect *r)
1708{
1709 int w_ratio, h_ratio, scale_factor, cur_ratio, i;
1710
1711 w_ratio = ctx->out_q.w / r->width;
1712 h_ratio = ctx->out_q.h / r->height;
1713
1714 scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio;
1715 scale_factor = clamp_val(scale_factor, 1, 8);
1716
1717 /* Align scale ratio to the nearest power of 2 */
1718 for (i = 0; i <= 3; ++i) {
1719 cur_ratio = 1 << i;
1720 if (scale_factor <= cur_ratio) {
1721 ctx->scale_factor = cur_ratio;
1722 break;
1723 }
1724 }
1725
1726 r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);
1727 r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);
1728
1729 ctx->crop_rect.width = r->width;
1730 ctx->crop_rect.height = r->height;
1731 ctx->crop_rect.left = 0;
1732 ctx->crop_rect.top = 0;
1733
1734 ctx->crop_altered = true;
1735
1736 return 0;
1737}
1738
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001739static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,
1740 struct v4l2_rect *r)
1741{
1742 struct v4l2_rect base_rect;
1743 int w_step, h_step;
1744
1745 switch (ctx->cap_q.fmt->fourcc) {
1746 case V4L2_PIX_FMT_NV12:
1747 case V4L2_PIX_FMT_NV21:
1748 w_step = 1;
1749 h_step = 2;
1750 break;
1751 case V4L2_PIX_FMT_YUV420:
1752 w_step = 2;
1753 h_step = 2;
1754 break;
1755 default:
1756 w_step = 1;
1757 h_step = 1;
1758 break;
1759 }
1760
1761 base_rect.top = 0;
1762 base_rect.left = 0;
1763 base_rect.width = ctx->out_q.w;
1764 base_rect.height = ctx->out_q.h;
1765
1766 r->width = round_down(r->width, w_step);
1767 r->height = round_down(r->height, h_step);
1768 r->left = round_down(r->left, 2);
1769 r->top = round_down(r->top, 2);
1770
Benoit Parrot030b1612020-05-28 15:26:05 +02001771 if (!v4l2_rect_enclosed(r, &base_rect))
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001772 return -EINVAL;
1773
1774 ctx->crop_rect.left = r->left;
1775 ctx->crop_rect.top = r->top;
1776 ctx->crop_rect.width = r->width;
1777 ctx->crop_rect.height = r->height;
1778
1779 ctx->crop_altered = true;
1780
1781 return 0;
1782}
1783
1784/*
1785 * V4L2 controls
1786 */
1787
Sachin Kamat9f3bd322012-05-10 03:38:40 -03001788static int s5p_jpeg_g_selection(struct file *file, void *priv,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001789 struct v4l2_selection *s)
1790{
Sylwester Nawrocki275de242012-02-17 11:38:09 -03001791 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001792
1793 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
Jacek Anaszewski38a6ef32014-04-10 04:32:15 -03001794 s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001795 return -EINVAL;
1796
1797 /* For JPEG blob active == default == bounds */
1798 switch (s->target) {
Sylwester Nawrockic1334822012-05-20 11:17:12 -03001799 case V4L2_SEL_TGT_CROP:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001800 case V4L2_SEL_TGT_CROP_BOUNDS:
1801 case V4L2_SEL_TGT_CROP_DEFAULT:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001802 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1803 s->r.width = ctx->out_q.w;
1804 s->r.height = ctx->out_q.h;
Jacek Anaszewskifac4d962014-07-11 12:19:45 -03001805 s->r.left = 0;
1806 s->r.top = 0;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001807 break;
Jacek Anaszewskifac4d962014-07-11 12:19:45 -03001808 case V4L2_SEL_TGT_COMPOSE:
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001809 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1810 case V4L2_SEL_TGT_COMPOSE_PADDED:
Jacek Anaszewskifac4d962014-07-11 12:19:45 -03001811 s->r.width = ctx->crop_rect.width;
1812 s->r.height = ctx->crop_rect.height;
1813 s->r.left = ctx->crop_rect.left;
1814 s->r.top = ctx->crop_rect.top;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001815 break;
1816 default:
1817 return -EINVAL;
1818 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001819 return 0;
1820}
1821
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001822/*
1823 * V4L2 controls
1824 */
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001825static int s5p_jpeg_s_selection(struct file *file, void *fh,
1826 struct v4l2_selection *s)
1827{
1828 struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
1829 struct v4l2_rect *rect = &s->r;
1830 int ret = -EINVAL;
1831
1832 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1833 return -EINVAL;
1834
1835 if (s->target == V4L2_SEL_TGT_COMPOSE) {
1836 if (ctx->mode != S5P_JPEG_DECODE)
1837 return -EINVAL;
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001838 if (ctx->jpeg->variant->hw3250_compat)
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001839 ret = exynos3250_jpeg_try_downscale(ctx, rect);
1840 } else if (s->target == V4L2_SEL_TGT_CROP) {
1841 if (ctx->mode != S5P_JPEG_ENCODE)
1842 return -EINVAL;
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001843 if (ctx->jpeg->variant->hw3250_compat)
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03001844 ret = exynos3250_jpeg_try_crop(ctx, rect);
1845 }
1846
1847 return ret;
1848}
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001849
1850static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001851{
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001852 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1853 struct s5p_jpeg *jpeg = ctx->jpeg;
1854 unsigned long flags;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001855
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001856 switch (ctrl->id) {
1857 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1858 spin_lock_irqsave(&jpeg->slock, flags);
Jacek Anaszewski303b0a92013-12-18 11:14:00 -03001859 ctrl->val = s5p_jpeg_to_user_subsampling(ctx);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001860 spin_unlock_irqrestore(&jpeg->slock, flags);
1861 break;
1862 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001863
1864 return 0;
1865}
1866
Jacek Anaszewski39c344c2014-07-11 12:19:48 -03001867static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
1868{
1869 switch (ctx->jpeg->variant->version) {
1870 case SJPEG_S5P:
1871 return 0;
1872 case SJPEG_EXYNOS3250:
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001873 case SJPEG_EXYNOS5420:
Jacek Anaszewski39c344c2014-07-11 12:19:48 -03001874 /*
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001875 * The exynos3250/compatible device can produce JPEG image only
Jacek Anaszewski39c344c2014-07-11 12:19:48 -03001876 * of 4:4:4 subsampling when given RGB32 source image.
1877 */
1878 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
1879 *ctrl_val = 0;
1880 break;
1881 case SJPEG_EXYNOS4:
1882 /*
1883 * The exynos4x12 device requires input raw image fourcc
1884 * to be V4L2_PIX_FMT_GREY if gray jpeg format
1885 * is to be set.
1886 */
1887 if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
1888 *ctrl_val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY)
1889 return -EINVAL;
1890 break;
1891 }
1892
1893 /*
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03001894 * The exynos4x12 and exynos3250/compatible devices require resulting
Jacek Anaszewski39c344c2014-07-11 12:19:48 -03001895 * jpeg subsampling not to be lower than the input raw image
1896 * subsampling.
1897 */
1898 if (ctx->out_q.fmt->subsampling > *ctrl_val)
1899 *ctrl_val = ctx->out_q.fmt->subsampling;
1900
1901 return 0;
1902}
1903
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001904static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
1905{
1906 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1907 unsigned long flags;
1908 int ret = 0;
1909
1910 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1911
Jacek Anaszewski39c344c2014-07-11 12:19:48 -03001912 if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING)
1913 ret = s5p_jpeg_adjust_subs_ctrl(ctx, &ctrl->val);
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001914
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001915 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1916 return ret;
1917}
1918
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001919static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001920{
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001921 struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
1922 unsigned long flags;
1923
1924 spin_lock_irqsave(&ctx->jpeg->slock, flags);
1925
1926 switch (ctrl->id) {
1927 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -03001928 ctx->compr_quality = ctrl->val;
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001929 break;
1930 case V4L2_CID_JPEG_RESTART_INTERVAL:
1931 ctx->restart_interval = ctrl->val;
1932 break;
1933 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1934 ctx->subsampling = ctrl->val;
1935 break;
1936 }
1937
1938 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
1939 return 0;
1940}
1941
1942static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {
1943 .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl,
Jacek Anaszewski11fbea32013-11-21 13:34:01 -03001944 .try_ctrl = s5p_jpeg_try_ctrl,
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001945 .s_ctrl = s5p_jpeg_s_ctrl,
1946};
1947
1948static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)
1949{
1950 unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */
1951 struct v4l2_ctrl *ctrl;
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001952 int ret;
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001953
1954 v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
1955
1956 if (ctx->mode == S5P_JPEG_ENCODE) {
1957 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1958 V4L2_CID_JPEG_COMPRESSION_QUALITY,
Jacek Anaszewski78e5a3c2013-11-25 06:58:08 -03001959 0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001960
1961 v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1962 V4L2_CID_JPEG_RESTART_INTERVAL,
Pawe? Chmiel19c624c2019-01-09 13:00:41 -05001963 0, 0xffff, 1, 0);
Jacek Anaszewskifdf9e2b2013-11-21 13:33:41 -03001964 if (ctx->jpeg->variant->version == SJPEG_S5P)
1965 mask = ~0x06; /* 422, 420 */
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001966 }
1967
1968 ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
1969 V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
1970 V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,
1971 V4L2_JPEG_CHROMA_SUBSAMPLING_422);
1972
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001973 if (ctx->ctrl_handler.error) {
1974 ret = ctx->ctrl_handler.error;
1975 goto error_free;
1976 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001977
1978 if (ctx->mode == S5P_JPEG_DECODE)
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03001979 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |
1980 V4L2_CTRL_FLAG_READ_ONLY;
Jacek Anaszewski088f8302013-11-25 06:58:15 -03001981
1982 ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
1983 if (ret < 0)
1984 goto error_free;
1985
1986 return ret;
1987
1988error_free:
1989 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1990 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03001991}
1992
1993static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
1994 .vidioc_querycap = s5p_jpeg_querycap,
1995
1996 .vidioc_enum_fmt_vid_cap = s5p_jpeg_enum_fmt_vid_cap,
1997 .vidioc_enum_fmt_vid_out = s5p_jpeg_enum_fmt_vid_out,
1998
1999 .vidioc_g_fmt_vid_cap = s5p_jpeg_g_fmt,
2000 .vidioc_g_fmt_vid_out = s5p_jpeg_g_fmt,
2001
2002 .vidioc_try_fmt_vid_cap = s5p_jpeg_try_fmt_vid_cap,
2003 .vidioc_try_fmt_vid_out = s5p_jpeg_try_fmt_vid_out,
2004
2005 .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap,
2006 .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out,
2007
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002008 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
2009 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
2010 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
2011 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002012
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002013 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
2014 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002015
2016 .vidioc_g_selection = s5p_jpeg_g_selection,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002017 .vidioc_s_selection = s5p_jpeg_s_selection,
henryhsu1c84e7f2017-06-30 10:15:46 -04002018
2019 .vidioc_subscribe_event = s5p_jpeg_subscribe_event,
2020 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002021};
2022
2023/*
2024 * ============================================================================
2025 * mem2mem callbacks
2026 * ============================================================================
2027 */
2028
2029static void s5p_jpeg_device_run(void *priv)
2030{
2031 struct s5p_jpeg_ctx *ctx = priv;
2032 struct s5p_jpeg *jpeg = ctx->jpeg;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002033 struct vb2_v4l2_buffer *src_buf, *dst_buf;
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002034 unsigned long src_addr, dst_addr, flags;
2035
2036 spin_lock_irqsave(&ctx->jpeg->slock, flags);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002037
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002038 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2039 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002040 src_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
2041 dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002042
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002043 s5p_jpeg_reset(jpeg->regs);
2044 s5p_jpeg_poweron(jpeg->regs);
2045 s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002046 if (ctx->mode == S5P_JPEG_ENCODE) {
2047 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002048 s5p_jpeg_input_raw_mode(jpeg->regs,
2049 S5P_JPEG_RAW_IN_565);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002050 else
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002051 s5p_jpeg_input_raw_mode(jpeg->regs,
2052 S5P_JPEG_RAW_IN_422);
2053 s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
2054 s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);
2055 s5p_jpeg_x(jpeg->regs, ctx->out_q.w);
2056 s5p_jpeg_y(jpeg->regs, ctx->out_q.h);
2057 s5p_jpeg_imgadr(jpeg->regs, src_addr);
2058 s5p_jpeg_jpgadr(jpeg->regs, dst_addr);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002059
2060 /* ultimately comes from sizeimage from userspace */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002061 s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002062
2063 /* JPEG RGB to YCbCr conversion matrix */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002064 s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
2065 s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
2066 s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
2067 s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
2068 s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
2069 s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
2070 s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
2071 s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
2072 s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002073
2074 /*
2075 * JPEG IP allows storing 4 quantization tables
2076 * We fill table 0 for luma and table 1 for chroma
2077 */
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03002078 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
2079 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002080 /* use table 0 for Y */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002081 s5p_jpeg_qtbl(jpeg->regs, 1, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002082 /* use table 1 for Cb and Cr*/
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002083 s5p_jpeg_qtbl(jpeg->regs, 2, 1);
2084 s5p_jpeg_qtbl(jpeg->regs, 3, 1);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002085
2086 /* Y, Cb, Cr use Huffman table 0 */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002087 s5p_jpeg_htbl_ac(jpeg->regs, 1);
2088 s5p_jpeg_htbl_dc(jpeg->regs, 1);
2089 s5p_jpeg_htbl_ac(jpeg->regs, 2);
2090 s5p_jpeg_htbl_dc(jpeg->regs, 2);
2091 s5p_jpeg_htbl_ac(jpeg->regs, 3);
2092 s5p_jpeg_htbl_dc(jpeg->regs, 3);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03002093 } else { /* S5P_JPEG_DECODE */
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002094 s5p_jpeg_rst_int_enable(jpeg->regs, true);
2095 s5p_jpeg_data_num_int_enable(jpeg->regs, true);
2096 s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03002097 if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002098 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03002099 else
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002100 s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
2101 s5p_jpeg_jpgadr(jpeg->regs, src_addr);
2102 s5p_jpeg_imgadr(jpeg->regs, dst_addr);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002103 }
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002104
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002105 s5p_jpeg_start(jpeg->regs);
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03002106
2107 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002108}
2109
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002110static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
2111{
2112 struct s5p_jpeg *jpeg = ctx->jpeg;
2113 struct s5p_jpeg_fmt *fmt;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002114 struct vb2_v4l2_buffer *vb;
Jacek Anaszewski12b05562015-03-05 10:56:25 -03002115 struct s5p_jpeg_addr jpeg_addr = {};
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002116 u32 pix_size, padding_bytes = 0;
2117
Tony K Nadackalcb0c3f52014-12-17 04:21:21 -03002118 jpeg_addr.cb = 0;
2119 jpeg_addr.cr = 0;
2120
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002121 pix_size = ctx->cap_q.w * ctx->cap_q.h;
2122
2123 if (ctx->mode == S5P_JPEG_ENCODE) {
2124 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2125 fmt = ctx->out_q.fmt;
2126 if (ctx->out_q.w % 2 && fmt->h_align > 0)
2127 padding_bytes = ctx->out_q.h;
2128 } else {
2129 fmt = ctx->cap_q.fmt;
2130 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2131 }
2132
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002133 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002134
2135 if (fmt->colplanes == 2) {
2136 jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;
2137 } else if (fmt->colplanes == 3) {
2138 jpeg_addr.cb = jpeg_addr.y + pix_size;
2139 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
2140 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
2141 else
2142 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
2143 }
2144
2145 exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);
2146}
2147
2148static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
2149{
2150 struct s5p_jpeg *jpeg = ctx->jpeg;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002151 struct vb2_v4l2_buffer *vb;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002152 unsigned int jpeg_addr = 0;
2153
2154 if (ctx->mode == S5P_JPEG_ENCODE)
2155 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2156 else
2157 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2158
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002159 jpeg_addr = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002160 if (jpeg->variant->version == SJPEG_EXYNOS5433 &&
2161 ctx->mode == S5P_JPEG_DECODE)
2162 jpeg_addr += ctx->out_q.sos;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002163 exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
2164}
2165
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002166static inline void exynos4_jpeg_set_img_fmt(void __iomem *base,
2167 unsigned int img_fmt)
2168{
2169 __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS4);
2170}
2171
2172static inline void exynos5433_jpeg_set_img_fmt(void __iomem *base,
2173 unsigned int img_fmt)
2174{
2175 __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS5433);
2176}
2177
2178static inline void exynos4_jpeg_set_enc_out_fmt(void __iomem *base,
2179 unsigned int out_fmt)
2180{
2181 __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS4);
2182}
2183
2184static inline void exynos5433_jpeg_set_enc_out_fmt(void __iomem *base,
2185 unsigned int out_fmt)
2186{
2187 __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS5433);
2188}
2189
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002190static void exynos4_jpeg_device_run(void *priv)
2191{
2192 struct s5p_jpeg_ctx *ctx = priv;
2193 struct s5p_jpeg *jpeg = ctx->jpeg;
2194 unsigned int bitstream_size;
2195 unsigned long flags;
2196
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002197 spin_lock_irqsave(&jpeg->slock, flags);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002198
2199 if (ctx->mode == S5P_JPEG_ENCODE) {
2200 exynos4_jpeg_sw_reset(jpeg->regs);
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002201 exynos4_jpeg_set_interrupt(jpeg->regs, jpeg->variant->version);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002202 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
2203
2204 exynos4_jpeg_set_huff_tbl(jpeg->regs);
2205
2206 /*
2207 * JPEG IP allows storing 4 quantization tables
2208 * We fill table 0 for luma and table 1 for chroma
2209 */
2210 exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
2211 exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
2212
2213 exynos4_jpeg_set_encode_tbl_select(jpeg->regs,
2214 ctx->compr_quality);
2215 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
2216 ctx->cap_q.h);
2217
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002218 if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) {
2219 exynos4_jpeg_set_enc_out_fmt(jpeg->regs,
2220 ctx->subsampling);
2221 exynos4_jpeg_set_img_fmt(jpeg->regs,
2222 ctx->out_q.fmt->fourcc);
2223 } else {
2224 exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
2225 ctx->subsampling);
2226 exynos5433_jpeg_set_img_fmt(jpeg->regs,
2227 ctx->out_q.fmt->fourcc);
2228 }
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002229 exynos4_jpeg_set_img_addr(ctx);
2230 exynos4_jpeg_set_jpeg_addr(ctx);
2231 exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
2232 ctx->out_q.fmt->fourcc);
2233 } else {
2234 exynos4_jpeg_sw_reset(jpeg->regs);
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002235 exynos4_jpeg_set_interrupt(jpeg->regs,
2236 jpeg->variant->version);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002237 exynos4_jpeg_set_img_addr(ctx);
2238 exynos4_jpeg_set_jpeg_addr(ctx);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002239
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002240 if (jpeg->variant->version == SJPEG_EXYNOS5433) {
2241 exynos4_jpeg_parse_huff_tbl(ctx);
2242 exynos4_jpeg_parse_decode_h_tbl(ctx);
2243
2244 exynos4_jpeg_parse_q_tbl(ctx);
2245 exynos4_jpeg_parse_decode_q_tbl(ctx);
2246
2247 exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
2248
2249 exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
2250 ctx->cap_q.h);
2251 exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
2252 ctx->subsampling);
2253 exynos5433_jpeg_set_img_fmt(jpeg->regs,
2254 ctx->cap_q.fmt->fourcc);
2255 bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 16);
2256 } else {
2257 exynos4_jpeg_set_img_fmt(jpeg->regs,
2258 ctx->cap_q.fmt->fourcc);
2259 bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
2260 }
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002261
2262 exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
2263 }
2264
Tony K Nadackale28e6f72017-08-08 07:27:04 -04002265 exynos4_jpeg_set_sys_int_enable(jpeg->regs, 1);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002266 exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
2267
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002268 spin_unlock_irqrestore(&jpeg->slock, flags);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002269}
2270
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002271static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
2272{
2273 struct s5p_jpeg *jpeg = ctx->jpeg;
2274 struct s5p_jpeg_fmt *fmt;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002275 struct vb2_v4l2_buffer *vb;
Jacek Anaszewski12b05562015-03-05 10:56:25 -03002276 struct s5p_jpeg_addr jpeg_addr = {};
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002277 u32 pix_size;
2278
2279 pix_size = ctx->cap_q.w * ctx->cap_q.h;
2280
2281 if (ctx->mode == S5P_JPEG_ENCODE) {
2282 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2283 fmt = ctx->out_q.fmt;
2284 } else {
2285 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2286 fmt = ctx->cap_q.fmt;
2287 }
2288
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002289 jpeg_addr.y = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002290
2291 if (fmt->colplanes == 2) {
2292 jpeg_addr.cb = jpeg_addr.y + pix_size;
2293 } else if (fmt->colplanes == 3) {
2294 jpeg_addr.cb = jpeg_addr.y + pix_size;
2295 if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
2296 jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
2297 else
2298 jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
2299 }
2300
2301 exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);
2302}
2303
2304static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
2305{
2306 struct s5p_jpeg *jpeg = ctx->jpeg;
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002307 struct vb2_v4l2_buffer *vb;
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002308 unsigned int jpeg_addr = 0;
2309
2310 if (ctx->mode == S5P_JPEG_ENCODE)
2311 vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
2312 else
2313 vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
2314
Ezequiel Garcia4a88f892019-02-08 11:17:45 -05002315 jpeg_addr = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002316 exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);
2317}
2318
2319static void exynos3250_jpeg_device_run(void *priv)
2320{
2321 struct s5p_jpeg_ctx *ctx = priv;
2322 struct s5p_jpeg *jpeg = ctx->jpeg;
2323 unsigned long flags;
2324
2325 spin_lock_irqsave(&ctx->jpeg->slock, flags);
2326
2327 exynos3250_jpeg_reset(jpeg->regs);
2328 exynos3250_jpeg_set_dma_num(jpeg->regs);
2329 exynos3250_jpeg_poweron(jpeg->regs);
2330 exynos3250_jpeg_clk_set(jpeg->regs);
2331 exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);
2332
2333 if (ctx->mode == S5P_JPEG_ENCODE) {
2334 exynos3250_jpeg_input_raw_fmt(jpeg->regs,
2335 ctx->out_q.fmt->fourcc);
2336 exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);
2337
2338 /*
2339 * JPEG IP allows storing 4 quantization tables
2340 * We fill table 0 for luma and table 1 for chroma
2341 */
2342 s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
2343 s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
2344 /* use table 0 for Y */
2345 exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);
2346 /* use table 1 for Cb and Cr*/
2347 exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
2348 exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
2349
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03002350 /*
2351 * Some SoCs require setting Huffman tables before each run
2352 */
2353 if (jpeg->variant->htbl_reinit) {
2354 s5p_jpeg_set_hdctbl(jpeg->regs);
2355 s5p_jpeg_set_hdctblg(jpeg->regs);
2356 s5p_jpeg_set_hactbl(jpeg->regs);
2357 s5p_jpeg_set_hactblg(jpeg->regs);
2358 }
2359
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002360 /* Y, Cb, Cr use Huffman table 0 */
2361 exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
2362 exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
2363 exynos3250_jpeg_htbl_ac(jpeg->regs, 2);
2364 exynos3250_jpeg_htbl_dc(jpeg->regs, 2);
2365 exynos3250_jpeg_htbl_ac(jpeg->regs, 3);
2366 exynos3250_jpeg_htbl_dc(jpeg->regs, 3);
2367
2368 exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);
2369 exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);
2370 exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,
2371 ctx->out_q.w);
2372 exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,
2373 ctx->crop_rect.top);
2374 exynos3250_jpeg_set_img_addr(ctx);
2375 exynos3250_jpeg_set_jpeg_addr(ctx);
2376 exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
2377
2378 /* ultimately comes from sizeimage from userspace */
2379 exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);
2380
2381 if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||
2382 ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||
2383 ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
2384 exynos3250_jpeg_set_y16(jpeg->regs, true);
2385 } else {
2386 exynos3250_jpeg_set_img_addr(ctx);
2387 exynos3250_jpeg_set_jpeg_addr(ctx);
2388 exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,
2389 ctx->cap_q.w);
2390 exynos3250_jpeg_offset(jpeg->regs, 0, 0);
2391 exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,
2392 ctx->scale_factor);
2393 exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);
2394 exynos3250_jpeg_output_raw_fmt(jpeg->regs,
2395 ctx->cap_q.fmt->fourcc);
2396 }
2397
2398 exynos3250_jpeg_interrupts_enable(jpeg->regs);
2399
2400 /* JPEG RGB to YCbCr conversion matrix */
2401 exynos3250_jpeg_coef(jpeg->regs, ctx->mode);
2402
2403 exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);
2404 jpeg->irq_status = 0;
2405 exynos3250_jpeg_start(jpeg->regs);
2406
2407 spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
2408}
2409
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002410static int s5p_jpeg_job_ready(void *priv)
2411{
2412 struct s5p_jpeg_ctx *ctx = priv;
2413
henryhsu1c84e7f2017-06-30 10:15:46 -04002414 if (ctx->mode == S5P_JPEG_DECODE) {
2415 /*
2416 * We have only one input buffer and one output buffer. If there
2417 * is a resolution change event, no need to continue decoding.
2418 */
2419 if (ctx->state == JPEGCTX_RESOLUTION_CHANGE)
2420 return 0;
2421
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002422 return ctx->hdr_parsed;
henryhsu1c84e7f2017-06-30 10:15:46 -04002423 }
2424
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002425 return 1;
2426}
2427
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002428static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
2429 .device_run = s5p_jpeg_device_run,
2430 .job_ready = s5p_jpeg_job_ready,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002431};
2432
2433static struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {
2434 .device_run = exynos3250_jpeg_device_run,
2435 .job_ready = s5p_jpeg_job_ready,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002436};
2437
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002438static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002439 .device_run = exynos4_jpeg_device_run,
2440 .job_ready = s5p_jpeg_job_ready,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002441};
2442
2443/*
2444 * ============================================================================
2445 * Queue operations
2446 * ============================================================================
2447 */
2448
Marek Szyprowski719c1742012-01-13 05:12:38 -03002449static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
Marek Szyprowski719c1742012-01-13 05:12:38 -03002450 unsigned int *nbuffers, unsigned int *nplanes,
Hans Verkuil36c0f8b2016-04-15 09:15:05 -03002451 unsigned int sizes[], struct device *alloc_devs[])
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002452{
2453 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
2454 struct s5p_jpeg_q_data *q_data = NULL;
2455 unsigned int size, count = *nbuffers;
2456
2457 q_data = get_q_data(ctx, vq->type);
2458 BUG_ON(q_data == NULL);
2459
2460 size = q_data->size;
2461
2462 /*
2463 * header is parsed during decoding and parsed information stored
2464 * in the context so we do not allow another buffer to overwrite it
2465 */
2466 if (ctx->mode == S5P_JPEG_DECODE)
2467 count = 1;
2468
2469 *nbuffers = count;
2470 *nplanes = 1;
2471 sizes[0] = size;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002472
2473 return 0;
2474}
2475
2476static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
2477{
2478 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2479 struct s5p_jpeg_q_data *q_data = NULL;
2480
2481 q_data = get_q_data(ctx, vb->vb2_queue->type);
2482 BUG_ON(q_data == NULL);
2483
2484 if (vb2_plane_size(vb, 0) < q_data->size) {
2485 pr_err("%s data will not fit into plane (%lu < %lu)\n",
2486 __func__, vb2_plane_size(vb, 0),
2487 (long)q_data->size);
2488 return -EINVAL;
2489 }
2490
2491 vb2_set_plane_payload(vb, 0, q_data->size);
2492
2493 return 0;
2494}
2495
henryhsu1c84e7f2017-06-30 10:15:46 -04002496static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx)
2497{
2498 struct s5p_jpeg_q_data *q_data = &ctx->cap_q;
2499
2500 q_data->w = ctx->out_q.w;
2501 q_data->h = ctx->out_q.h;
2502
2503 /*
2504 * This call to jpeg_bound_align_image() takes care of width and
2505 * height values alignment when user space calls the QBUF of
2506 * OUTPUT buffer after the S_FMT of CAPTURE buffer.
2507 * Please note that on Exynos4x12 SoCs, resigning from executing
2508 * S_FMT on capture buffer for each JPEG image can result in a
2509 * hardware hangup if subsampling is lower than the one of input
2510 * JPEG.
2511 */
2512 jpeg_bound_align_image(ctx, &q_data->w, S5P_JPEG_MIN_WIDTH,
2513 S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align,
2514 &q_data->h, S5P_JPEG_MIN_HEIGHT,
2515 S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align);
2516
2517 q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
2518}
2519
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002520static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
2521{
Junghak Sung2d700712015-09-22 10:30:30 -03002522 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002523 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2524
2525 if (ctx->mode == S5P_JPEG_DECODE &&
2526 vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
henryhsu1c84e7f2017-06-30 10:15:46 -04002527 static const struct v4l2_event ev_src_ch = {
2528 .type = V4L2_EVENT_SOURCE_CHANGE,
2529 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
2530 };
2531 struct vb2_queue *dst_vq;
2532 u32 ori_w;
2533 u32 ori_h;
2534
2535 dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
2536 V4L2_BUF_TYPE_VIDEO_CAPTURE);
2537 ori_w = ctx->out_q.w;
2538 ori_h = ctx->out_q.h;
Shuah Khan605b8922016-07-14 17:01:56 -03002539
Thierry Escande14a2de12017-06-30 10:15:43 -04002540 ctx->hdr_parsed = s5p_jpeg_parse_hdr(&ctx->out_q,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002541 (unsigned long)vb2_plane_vaddr(vb, 0),
2542 min((unsigned long)ctx->out_q.size,
Jacek Anaszewskif8433962013-11-21 13:33:09 -03002543 vb2_get_plane_payload(vb, 0)), ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002544 if (!ctx->hdr_parsed) {
2545 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
2546 return;
2547 }
2548
Tony K Nadackal5ea3bf22017-06-30 10:15:40 -04002549 /*
henryhsu1c84e7f2017-06-30 10:15:46 -04002550 * If there is a resolution change event, only update capture
2551 * queue when it is not streaming. Otherwise, update it in
2552 * STREAMOFF. See s5p_jpeg_stop_streaming for detail.
Tony K Nadackal5ea3bf22017-06-30 10:15:40 -04002553 */
henryhsu1c84e7f2017-06-30 10:15:46 -04002554 if (ctx->out_q.w != ori_w || ctx->out_q.h != ori_h) {
2555 v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
2556 if (vb2_is_streaming(dst_vq))
2557 ctx->state = JPEGCTX_RESOLUTION_CHANGE;
2558 else
2559 s5p_jpeg_set_capture_queue_data(ctx);
2560 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002561 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002562
Junghak Sung2d700712015-09-22 10:30:30 -03002563 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002564}
2565
2566static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
2567{
2568 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
2569 int ret;
2570
2571 ret = pm_runtime_get_sync(ctx->jpeg->dev);
2572
2573 return ret > 0 ? 0 : ret;
2574}
2575
Hans Verkuile37559b2014-04-17 02:47:21 -03002576static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002577{
2578 struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
2579
henryhsu1c84e7f2017-06-30 10:15:46 -04002580 /*
2581 * STREAMOFF is an acknowledgment for resolution change event.
2582 * Before STREAMOFF, we still have to return the old resolution and
2583 * subsampling. Update capture queue when the stream is off.
2584 */
2585 if (ctx->state == JPEGCTX_RESOLUTION_CHANGE &&
2586 q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2587 s5p_jpeg_set_capture_queue_data(ctx);
2588 ctx->state = JPEGCTX_RUNNING;
2589 }
2590
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002591 pm_runtime_put(ctx->jpeg->dev);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002592}
2593
Julia Lawallb7b361f02016-09-08 20:59:10 -03002594static const struct vb2_ops s5p_jpeg_qops = {
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002595 .queue_setup = s5p_jpeg_queue_setup,
2596 .buf_prepare = s5p_jpeg_buf_prepare,
2597 .buf_queue = s5p_jpeg_buf_queue,
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002598 .wait_prepare = vb2_ops_wait_prepare,
2599 .wait_finish = vb2_ops_wait_finish,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002600 .start_streaming = s5p_jpeg_start_streaming,
2601 .stop_streaming = s5p_jpeg_stop_streaming,
2602};
2603
2604static int queue_init(void *priv, struct vb2_queue *src_vq,
2605 struct vb2_queue *dst_vq)
2606{
2607 struct s5p_jpeg_ctx *ctx = priv;
2608 int ret;
2609
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002610 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2611 src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
2612 src_vq->drv_priv = ctx;
2613 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
2614 src_vq->ops = &s5p_jpeg_qops;
2615 src_vq->mem_ops = &vb2_dma_contig_memops;
Sakari Ailusade48682014-02-25 19:12:19 -03002616 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002617 src_vq->lock = &ctx->jpeg->lock;
Hans Verkuilc781e4a2016-02-15 14:25:09 -02002618 src_vq->dev = ctx->jpeg->dev;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002619
2620 ret = vb2_queue_init(src_vq);
2621 if (ret)
2622 return ret;
2623
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002624 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2625 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
2626 dst_vq->drv_priv = ctx;
2627 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
2628 dst_vq->ops = &s5p_jpeg_qops;
2629 dst_vq->mem_ops = &vb2_dma_contig_memops;
Sakari Ailusade48682014-02-25 19:12:19 -03002630 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002631 dst_vq->lock = &ctx->jpeg->lock;
Hans Verkuilc781e4a2016-02-15 14:25:09 -02002632 dst_vq->dev = ctx->jpeg->dev;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002633
2634 return vb2_queue_init(dst_vq);
2635}
2636
2637/*
2638 * ============================================================================
2639 * ISR
2640 * ============================================================================
2641 */
2642
2643static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
2644{
2645 struct s5p_jpeg *jpeg = dev_id;
2646 struct s5p_jpeg_ctx *curr_ctx;
Junghak Sung2d700712015-09-22 10:30:30 -03002647 struct vb2_v4l2_buffer *src_buf, *dst_buf;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002648 unsigned long payload_size = 0;
2649 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
2650 bool enc_jpeg_too_large = false;
2651 bool timer_elapsed = false;
2652 bool op_completed = false;
2653
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002654 spin_lock(&jpeg->slock);
2655
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002656 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2657
Sylwester Nawrocki718cf4a2013-08-25 17:16:56 -03002658 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2659 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002660
2661 if (curr_ctx->mode == S5P_JPEG_ENCODE)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002662 enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);
2663 timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);
2664 op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002665 if (curr_ctx->mode == S5P_JPEG_DECODE)
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002666 op_completed = op_completed &&
2667 s5p_jpeg_stream_stat_ok(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002668
2669 if (enc_jpeg_too_large) {
2670 state = VB2_BUF_STATE_ERROR;
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002671 s5p_jpeg_clear_enc_stream_stat(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002672 } else if (timer_elapsed) {
2673 state = VB2_BUF_STATE_ERROR;
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002674 s5p_jpeg_clear_timer_stat(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002675 } else if (!op_completed) {
2676 state = VB2_BUF_STATE_ERROR;
2677 } else {
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002678 payload_size = s5p_jpeg_compressed_size(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002679 }
2680
Junghak Sung2d700712015-09-22 10:30:30 -03002681 dst_buf->timecode = src_buf->timecode;
Junghak Sungd6dd6452015-11-03 08:16:37 -02002682 dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
Junghak Sung2d700712015-09-22 10:30:30 -03002683 dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
2684 dst_buf->flags |=
2685 src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
Kamil Debskiaca326a2013-04-24 10:08:02 -03002686
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002687 v4l2_m2m_buf_done(src_buf, state);
2688 if (curr_ctx->mode == S5P_JPEG_ENCODE)
Junghak Sung2d700712015-09-22 10:30:30 -03002689 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002690 v4l2_m2m_buf_done(dst_buf, state);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002691
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002692 curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002693 spin_unlock(&jpeg->slock);
Andrzej Pietrasiewiczfb6f8c02012-02-20 07:32:25 -03002694
Jacek Anaszewski9f7b62d2013-12-18 09:32:50 -03002695 s5p_jpeg_clear_int(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002696
Alexandre Courbot17d716e2017-04-25 03:19:43 -03002697 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002698 return IRQ_HANDLED;
2699}
2700
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002701static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
2702{
2703 unsigned int int_status;
Junghak Sung2d700712015-09-22 10:30:30 -03002704 struct vb2_v4l2_buffer *src_vb, *dst_vb;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002705 struct s5p_jpeg *jpeg = priv;
2706 struct s5p_jpeg_ctx *curr_ctx;
2707 unsigned long payload_size = 0;
2708
2709 spin_lock(&jpeg->slock);
2710
Tony K Nadackale28e6f72017-08-08 07:27:04 -04002711 exynos4_jpeg_set_sys_int_enable(jpeg->regs, 0);
2712
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002713 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2714
2715 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2716 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2717
2718 int_status = exynos4_jpeg_get_int_status(jpeg->regs);
2719
2720 if (int_status) {
2721 switch (int_status & 0x1f) {
2722 case 0x1:
2723 jpeg->irq_ret = ERR_PROT;
2724 break;
2725 case 0x2:
2726 jpeg->irq_ret = OK_ENC_OR_DEC;
2727 break;
2728 case 0x4:
2729 jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;
2730 break;
2731 case 0x8:
2732 jpeg->irq_ret = ERR_MULTI_SCAN;
2733 break;
2734 case 0x10:
2735 jpeg->irq_ret = ERR_FRAME;
2736 break;
2737 default:
2738 jpeg->irq_ret = ERR_UNKNOWN;
2739 break;
2740 }
2741 } else {
2742 jpeg->irq_ret = ERR_UNKNOWN;
2743 }
2744
2745 if (jpeg->irq_ret == OK_ENC_OR_DEC) {
2746 if (curr_ctx->mode == S5P_JPEG_ENCODE) {
2747 payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
Junghak Sung2d700712015-09-22 10:30:30 -03002748 vb2_set_plane_payload(&dst_vb->vb2_buf,
2749 0, payload_size);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002750 }
2751 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
2752 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
2753 } else {
2754 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
2755 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
2756 }
2757
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03002758 if (jpeg->variant->version == SJPEG_EXYNOS4)
2759 curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002760
Andrzej Pietrasiewicz630dde62017-08-08 07:27:05 -04002761 exynos4_jpeg_set_enc_dec_mode(jpeg->regs, S5P_JPEG_DISABLE);
2762
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002763 spin_unlock(&jpeg->slock);
Alexandre Courbot17d716e2017-04-25 03:19:43 -03002764
2765 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002766 return IRQ_HANDLED;
2767}
2768
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002769static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
2770{
2771 struct s5p_jpeg *jpeg = dev_id;
2772 struct s5p_jpeg_ctx *curr_ctx;
Junghak Sung2d700712015-09-22 10:30:30 -03002773 struct vb2_v4l2_buffer *src_buf, *dst_buf;
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002774 unsigned long payload_size = 0;
2775 enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
2776 bool interrupt_timeout = false;
henryhsu80cdaca2017-06-30 10:15:47 -04002777 bool stream_error = false;
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002778 u32 irq_status;
2779
2780 spin_lock(&jpeg->slock);
2781
2782 irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);
2783 if (irq_status & EXYNOS3250_TIMER_INT_STAT) {
2784 exynos3250_jpeg_clear_timer_status(jpeg->regs);
2785 interrupt_timeout = true;
2786 dev_err(jpeg->dev, "Interrupt timeout occurred.\n");
2787 }
2788
2789 irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);
2790 exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);
2791
2792 jpeg->irq_status |= irq_status;
2793
henryhsu80cdaca2017-06-30 10:15:47 -04002794 if (jpeg->variant->version == SJPEG_EXYNOS5420 &&
2795 irq_status & EXYNOS3250_STREAM_STAT) {
2796 stream_error = true;
2797 dev_err(jpeg->dev, "Syntax error or unrecoverable error occurred.\n");
2798 }
2799
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002800 curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
2801
2802 if (!curr_ctx)
2803 goto exit_unlock;
2804
2805 if ((irq_status & EXYNOS3250_HEADER_STAT) &&
2806 (curr_ctx->mode == S5P_JPEG_DECODE)) {
2807 exynos3250_jpeg_rstart(jpeg->regs);
2808 goto exit_unlock;
2809 }
2810
2811 if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |
2812 EXYNOS3250_WDMA_DONE |
2813 EXYNOS3250_RDMA_DONE |
2814 EXYNOS3250_RESULT_STAT))
2815 payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);
henryhsu80cdaca2017-06-30 10:15:47 -04002816 else if (interrupt_timeout || stream_error)
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002817 state = VB2_BUF_STATE_ERROR;
2818 else
2819 goto exit_unlock;
2820
2821 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
2822 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
2823
Junghak Sung2d700712015-09-22 10:30:30 -03002824 dst_buf->timecode = src_buf->timecode;
Junghak Sungd6dd6452015-11-03 08:16:37 -02002825 dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002826
2827 v4l2_m2m_buf_done(src_buf, state);
2828 if (curr_ctx->mode == S5P_JPEG_ENCODE)
Junghak Sung2d700712015-09-22 10:30:30 -03002829 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002830 v4l2_m2m_buf_done(dst_buf, state);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002831
2832 curr_ctx->subsampling =
2833 exynos3250_jpeg_get_subsampling_mode(jpeg->regs);
Alexandre Courbot17d716e2017-04-25 03:19:43 -03002834
2835 spin_unlock(&jpeg->slock);
2836
2837 v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
2838 return IRQ_HANDLED;
2839
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002840exit_unlock:
2841 spin_unlock(&jpeg->slock);
2842 return IRQ_HANDLED;
2843}
2844
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002845static void *jpeg_get_drv_data(struct device *dev);
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002846
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002847/*
2848 * ============================================================================
2849 * Driver basic infrastructure
2850 * ============================================================================
2851 */
2852
2853static int s5p_jpeg_probe(struct platform_device *pdev)
2854{
2855 struct s5p_jpeg *jpeg;
2856 struct resource *res;
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03002857 int i, ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002858
2859 /* JPEG IP abstraction struct */
Sachin Kamat5b58b952012-05-14 06:33:34 -03002860 jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002861 if (!jpeg)
2862 return -ENOMEM;
2863
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03002864 jpeg->variant = jpeg_get_drv_data(&pdev->dev);
Baskov Evgeniy0862d952020-11-13 17:06:25 +01002865 if (!jpeg->variant)
2866 return -ENODEV;
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002867
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002868 mutex_init(&jpeg->lock);
Sylwester Nawrocki15f4bc32012-02-17 11:39:36 -03002869 spin_lock_init(&jpeg->slock);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002870 jpeg->dev = &pdev->dev;
2871
2872 /* memory-mapped registers */
2873 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002874
Thierry Redingf23999e2013-01-21 06:09:07 -03002875 jpeg->regs = devm_ioremap_resource(&pdev->dev, res);
2876 if (IS_ERR(jpeg->regs))
2877 return PTR_ERR(jpeg->regs);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002878
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002879 /* interrupt service routine registration */
2880 jpeg->irq = ret = platform_get_irq(pdev, 0);
2881 if (ret < 0) {
2882 dev_err(&pdev->dev, "cannot find IRQ\n");
Sachin Kamat5b58b952012-05-14 06:33:34 -03002883 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002884 }
2885
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03002886 ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,
2887 0, dev_name(&pdev->dev), jpeg);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002888 if (ret) {
2889 dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
Sachin Kamat5b58b952012-05-14 06:33:34 -03002890 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002891 }
2892
2893 /* clocks */
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03002894 for (i = 0; i < jpeg->variant->num_clocks; i++) {
2895 jpeg->clocks[i] = devm_clk_get(&pdev->dev,
2896 jpeg->variant->clk_names[i]);
2897 if (IS_ERR(jpeg->clocks[i])) {
2898 dev_err(&pdev->dev, "failed to get clock: %s\n",
2899 jpeg->variant->clk_names[i]);
2900 return PTR_ERR(jpeg->clocks[i]);
2901 }
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002902 }
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03002903
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002904 /* v4l2 device */
2905 ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
2906 if (ret) {
2907 dev_err(&pdev->dev, "Failed to register v4l2 device\n");
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03002908 return ret;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002909 }
2910
2911 /* mem2mem device */
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03002912 jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002913 if (IS_ERR(jpeg->m2m_dev)) {
2914 v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
2915 ret = PTR_ERR(jpeg->m2m_dev);
2916 goto device_register_rollback;
2917 }
2918
Marek Szyprowski712b6172016-05-24 09:16:07 +02002919 vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002920
2921 /* JPEG encoder /dev/videoX node */
2922 jpeg->vfd_encoder = video_device_alloc();
2923 if (!jpeg->vfd_encoder) {
2924 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2925 ret = -ENOMEM;
Hans Verkuilc781e4a2016-02-15 14:25:09 -02002926 goto m2m_init_rollback;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002927 }
Seung-Woo Kimbaaf0462013-10-10 04:45:56 -03002928 snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),
2929 "%s-enc", S5P_JPEG_M2M_NAME);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002930 jpeg->vfd_encoder->fops = &s5p_jpeg_fops;
2931 jpeg->vfd_encoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2932 jpeg->vfd_encoder->minor = -1;
2933 jpeg->vfd_encoder->release = video_device_release;
2934 jpeg->vfd_encoder->lock = &jpeg->lock;
2935 jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev;
Hans Verkuil954f3402012-09-05 06:05:50 -03002936 jpeg->vfd_encoder->vfl_dir = VFL_DIR_M2M;
Hans Verkuil994587c2019-06-26 02:51:41 -04002937 jpeg->vfd_encoder->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002938
Hans Verkuil70cad4492020-02-03 12:41:18 +01002939 ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_VIDEO, -1);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002940 if (ret) {
2941 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
Andrzej Pietrasiewicz7a1d4e72015-07-03 07:04:38 -03002942 video_device_release(jpeg->vfd_encoder);
Hans Verkuilc781e4a2016-02-15 14:25:09 -02002943 goto m2m_init_rollback;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002944 }
2945
2946 video_set_drvdata(jpeg->vfd_encoder, jpeg);
2947 v4l2_info(&jpeg->v4l2_dev,
2948 "encoder device registered as /dev/video%d\n",
2949 jpeg->vfd_encoder->num);
2950
2951 /* JPEG decoder /dev/videoX node */
2952 jpeg->vfd_decoder = video_device_alloc();
2953 if (!jpeg->vfd_decoder) {
2954 v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
2955 ret = -ENOMEM;
2956 goto enc_vdev_register_rollback;
2957 }
Seung-Woo Kimbaaf0462013-10-10 04:45:56 -03002958 snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),
2959 "%s-dec", S5P_JPEG_M2M_NAME);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002960 jpeg->vfd_decoder->fops = &s5p_jpeg_fops;
2961 jpeg->vfd_decoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
2962 jpeg->vfd_decoder->minor = -1;
2963 jpeg->vfd_decoder->release = video_device_release;
2964 jpeg->vfd_decoder->lock = &jpeg->lock;
2965 jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev;
Jacek Anaszewski7f7d8fe2013-09-11 06:17:45 -03002966 jpeg->vfd_decoder->vfl_dir = VFL_DIR_M2M;
Hans Verkuil994587c2019-06-26 02:51:41 -04002967 jpeg->vfd_decoder->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002968
Hans Verkuil70cad4492020-02-03 12:41:18 +01002969 ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_VIDEO, -1);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002970 if (ret) {
2971 v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
Andrzej Pietrasiewicz7a1d4e72015-07-03 07:04:38 -03002972 video_device_release(jpeg->vfd_decoder);
2973 goto enc_vdev_register_rollback;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002974 }
2975
2976 video_set_drvdata(jpeg->vfd_decoder, jpeg);
2977 v4l2_info(&jpeg->v4l2_dev,
2978 "decoder device registered as /dev/video%d\n",
2979 jpeg->vfd_decoder->num);
2980
2981 /* final statements & power management */
2982 platform_set_drvdata(pdev, jpeg);
2983
2984 pm_runtime_enable(&pdev->dev);
2985
2986 v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
2987
2988 return 0;
2989
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002990enc_vdev_register_rollback:
2991 video_unregister_device(jpeg->vfd_encoder);
2992
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002993m2m_init_rollback:
2994 v4l2_m2m_release(jpeg->m2m_dev);
2995
2996device_register_rollback:
2997 v4l2_device_unregister(&jpeg->v4l2_dev);
2998
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03002999 return ret;
3000}
3001
3002static int s5p_jpeg_remove(struct platform_device *pdev)
3003{
3004 struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003005 int i;
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003006
3007 pm_runtime_disable(jpeg->dev);
3008
3009 video_unregister_device(jpeg->vfd_decoder);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003010 video_unregister_device(jpeg->vfd_encoder);
Marek Szyprowski712b6172016-05-24 09:16:07 +02003011 vb2_dma_contig_clear_max_seg_size(&pdev->dev);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003012 v4l2_m2m_release(jpeg->m2m_dev);
3013 v4l2_device_unregister(&jpeg->v4l2_dev);
3014
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003015 if (!pm_runtime_status_suspended(&pdev->dev)) {
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003016 for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
3017 clk_disable_unprepare(jpeg->clocks[i]);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003018 }
Jacek Anaszewskif1347132013-11-25 06:58:13 -03003019
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003020 return 0;
3021}
3022
Rafael J. Wysockie243c7c2014-12-04 01:10:10 +01003023#ifdef CONFIG_PM
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003024static int s5p_jpeg_runtime_suspend(struct device *dev)
3025{
Jacek Anaszewskif1347132013-11-25 06:58:13 -03003026 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003027 int i;
Jacek Anaszewskif1347132013-11-25 06:58:13 -03003028
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003029 for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
3030 clk_disable_unprepare(jpeg->clocks[i]);
Jacek Anaszewskif1347132013-11-25 06:58:13 -03003031
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003032 return 0;
3033}
3034
3035static int s5p_jpeg_runtime_resume(struct device *dev)
3036{
3037 struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03003038 unsigned long flags;
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003039 int i, ret;
Jacek Anaszewskif1347132013-11-25 06:58:13 -03003040
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003041 for (i = 0; i < jpeg->variant->num_clocks; i++) {
3042 ret = clk_prepare_enable(jpeg->clocks[i]);
3043 if (ret) {
Flavio Ceolinb6852a62017-12-06 11:37:45 -05003044 while (--i >= 0)
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003045 clk_disable_unprepare(jpeg->clocks[i]);
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003046 return ret;
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003047 }
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003048 }
3049
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03003050 spin_lock_irqsave(&jpeg->slock, flags);
3051
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003052 /*
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003053 * JPEG IP allows storing two Huffman tables for each component.
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003054 * We fill table 0 for each component and do this here only
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03003055 * for S5PC210 and Exynos3250 SoCs. Exynos4x12 and Exynos542x SoC
3056 * require programming their Huffman tables each time the encoding
3057 * process is initialized, and thus it is accomplished in the
3058 * device_run callback of m2m_ops.
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003059 */
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03003060 if (!jpeg->variant->htbl_reinit) {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003061 s5p_jpeg_set_hdctbl(jpeg->regs);
3062 s5p_jpeg_set_hdctblg(jpeg->regs);
3063 s5p_jpeg_set_hactbl(jpeg->regs);
3064 s5p_jpeg_set_hactblg(jpeg->regs);
3065 }
Jacek Anaszewski31dc0ac2013-11-25 06:58:12 -03003066
Jacek Anaszewskib3c932a2013-11-25 06:58:14 -03003067 spin_unlock_irqrestore(&jpeg->slock, flags);
3068
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003069 return 0;
3070}
Rafael J. Wysockie243c7c2014-12-04 01:10:10 +01003071#endif /* CONFIG_PM */
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003072
3073static const struct dev_pm_ops s5p_jpeg_pm_ops = {
Marek Szyprowski3b92fed2016-08-31 09:55:59 -03003074 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
3075 pm_runtime_force_resume)
Shuah Khan605b8922016-07-14 17:01:56 -03003076 SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume,
3077 NULL)
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003078};
3079
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003080static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
3081 .version = SJPEG_S5P,
3082 .jpeg_irq = s5p_jpeg_irq,
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03003083 .m2m_ops = &s5p_jpeg_m2m_ops,
Jacek Anaszewskib2451682014-04-10 04:32:11 -03003084 .fmt_ver_flag = SJPEG_FMT_FLAG_S5P,
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003085 .clk_names = {"jpeg"},
3086 .num_clocks = 1,
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03003087};
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003088
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003089static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
3090 .version = SJPEG_EXYNOS3250,
3091 .jpeg_irq = exynos3250_jpeg_irq,
3092 .m2m_ops = &exynos3250_jpeg_m2m_ops,
3093 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250,
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03003094 .hw3250_compat = 1,
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003095 .clk_names = {"jpeg", "sclk"},
3096 .num_clocks = 2,
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003097};
3098
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003099static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
3100 .version = SJPEG_EXYNOS4,
3101 .jpeg_irq = exynos4_jpeg_irq,
Jacek Anaszewskibf689bb2014-04-10 04:32:13 -03003102 .m2m_ops = &exynos4_jpeg_m2m_ops,
Jacek Anaszewskib2451682014-04-10 04:32:11 -03003103 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03003104 .htbl_reinit = 1,
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003105 .clk_names = {"jpeg"},
3106 .num_clocks = 1,
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03003107 .hw_ex4_compat = 1,
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03003108};
3109
3110static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
3111 .version = SJPEG_EXYNOS5420,
3112 .jpeg_irq = exynos3250_jpeg_irq, /* intentionally 3250 */
3113 .m2m_ops = &exynos3250_jpeg_m2m_ops, /* intentionally 3250 */
3114 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250, /* intentionally 3250 */
3115 .hw3250_compat = 1,
3116 .htbl_reinit = 1,
Marek Szyprowskib95a24d2015-09-18 11:20:57 -03003117 .clk_names = {"jpeg"},
3118 .num_clocks = 1,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003119};
3120
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03003121static struct s5p_jpeg_variant exynos5433_jpeg_drvdata = {
3122 .version = SJPEG_EXYNOS5433,
3123 .jpeg_irq = exynos4_jpeg_irq,
3124 .m2m_ops = &exynos4_jpeg_m2m_ops,
3125 .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4,
3126 .htbl_reinit = 1,
3127 .clk_names = {"pclk", "aclk", "aclk_xiu", "sclk"},
3128 .num_clocks = 4,
3129 .hw_ex4_compat = 1,
3130};
3131
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003132static const struct of_device_id samsung_jpeg_match[] = {
3133 {
3134 .compatible = "samsung,s5pv210-jpeg",
3135 .data = &s5p_jpeg_drvdata,
3136 }, {
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003137 .compatible = "samsung,exynos3250-jpeg",
3138 .data = &exynos3250_jpeg_drvdata,
3139 }, {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003140 .compatible = "samsung,exynos4210-jpeg",
Jacek Anaszewski3246fda2014-07-11 12:19:42 -03003141 .data = &exynos4_jpeg_drvdata,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003142 }, {
3143 .compatible = "samsung,exynos4212-jpeg",
3144 .data = &exynos4_jpeg_drvdata,
Andrzej Pietrasiewicz7c15fd42015-03-09 09:32:46 -03003145 }, {
3146 .compatible = "samsung,exynos5420-jpeg",
3147 .data = &exynos5420_jpeg_drvdata,
Andrzej Pietrasiewicz6c96dbb2015-09-18 11:20:58 -03003148 }, {
3149 .compatible = "samsung,exynos5433-jpeg",
3150 .data = &exynos5433_jpeg_drvdata,
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003151 },
3152 {},
3153};
3154
3155MODULE_DEVICE_TABLE(of, samsung_jpeg_match);
3156
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03003157static void *jpeg_get_drv_data(struct device *dev)
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003158{
3159 struct s5p_jpeg_variant *driver_data = NULL;
3160 const struct of_device_id *match;
3161
Jacek Anaszewski79a38a82014-04-10 04:32:14 -03003162 if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
3163 return &s5p_jpeg_drvdata;
3164
3165 match = of_match_node(samsung_jpeg_match, dev->of_node);
3166
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003167 if (match)
3168 driver_data = (struct s5p_jpeg_variant *)match->data;
3169
3170 return driver_data;
3171}
Sylwester Nawrockif7074ab2013-08-18 16:14:27 -03003172
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003173static struct platform_driver s5p_jpeg_driver = {
3174 .probe = s5p_jpeg_probe,
3175 .remove = s5p_jpeg_remove,
3176 .driver = {
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003177 .of_match_table = of_match_ptr(samsung_jpeg_match),
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003178 .name = S5P_JPEG_M2M_NAME,
3179 .pm = &s5p_jpeg_pm_ops,
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003180 },
3181};
3182
Sachin Kamat87e942942012-07-03 05:54:33 -03003183module_platform_driver(s5p_jpeg_driver);
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003184
Andrzej Pietrasiewicz66e988e2018-12-13 08:31:07 -05003185MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>");
Jacek Anaszewski80529ae52013-12-18 11:04:44 -03003186MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
Andrzej Pietrasiewiczbb677f32011-11-24 11:15:23 -03003187MODULE_DESCRIPTION("Samsung JPEG codec driver");
3188MODULE_LICENSE("GPL");