1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * V4L2 driver for the JPEG encoder/decoder from i.MX8QXP/i.MX8QM application |
4 | * processors. |
5 | * |
6 | * The multi-planar buffers API is used. |
7 | * |
8 | * Baseline and extended sequential jpeg decoding is supported. |
9 | * Progressive jpeg decoding is not supported by the IP. |
10 | * Supports encode and decode of various formats: |
11 | * YUV444, YUV422, YUV420, BGR, ABGR, Gray |
12 | * YUV420 is the only multi-planar format supported. |
13 | * Minimum resolution is 64 x 64, maximum 8192 x 8192. |
14 | * To achieve 8192 x 8192, modify in defconfig: CONFIG_CMA_SIZE_MBYTES=320 |
15 | * The alignment requirements for the resolution depend on the format, |
16 | * multiple of 16 resolutions should work for all formats. |
17 | * Special workarounds are made in the driver to support NV12 1080p. |
18 | * When decoding, the driver detects image resolution and pixel format |
19 | * from the jpeg stream, by parsing the jpeg markers. |
20 | * |
21 | * The IP has 4 slots available for context switching, but only slot 0 |
22 | * was fully tested to work. Context switching is not used by the driver. |
23 | * Each driver instance (context) allocates a slot for itself, but this |
24 | * is postponed until device_run, to allow unlimited opens. |
25 | * |
26 | * The driver submits jobs to the IP by setting up a descriptor for the |
27 | * used slot, and then validating it. The encoder has an additional descriptor |
28 | * for the configuration phase. The driver expects FRM_DONE interrupt from |
29 | * IP to mark the job as finished. |
30 | * |
31 | * The decoder IP has some limitations regarding the component ID's, |
32 | * but the driver works around this by replacing them in the jpeg stream. |
33 | * |
34 | * A module parameter is available for debug purpose (jpeg_tracing), to enable |
35 | * it, enable dynamic debug for this module and: |
36 | * echo 1 > /sys/module/mxc_jpeg_encdec/parameters/jpeg_tracing |
37 | * |
38 | * This is inspired by the drivers/media/platform/samsung/s5p-jpeg driver |
39 | * |
40 | * Copyright 2018-2019 NXP |
41 | */ |
42 | |
43 | #include <linux/kernel.h> |
44 | #include <linux/module.h> |
45 | #include <linux/io.h> |
46 | #include <linux/clk.h> |
47 | #include <linux/of_platform.h> |
48 | #include <linux/platform_device.h> |
49 | #include <linux/slab.h> |
50 | #include <linux/irqreturn.h> |
51 | #include <linux/interrupt.h> |
52 | #include <linux/pm_runtime.h> |
53 | #include <linux/pm_domain.h> |
54 | #include <linux/string.h> |
55 | |
56 | #include <media/v4l2-jpeg.h> |
57 | #include <media/v4l2-mem2mem.h> |
58 | #include <media/v4l2-ioctl.h> |
59 | #include <media/v4l2-common.h> |
60 | #include <media/v4l2-event.h> |
61 | #include <media/videobuf2-dma-contig.h> |
62 | |
63 | #include "mxc-jpeg-hw.h" |
64 | #include "mxc-jpeg.h" |
65 | |
66 | static const struct mxc_jpeg_fmt mxc_formats[] = { |
67 | { |
68 | .name = "JPEG" , |
69 | .fourcc = V4L2_PIX_FMT_JPEG, |
70 | .subsampling = -1, |
71 | .nc = -1, |
72 | .mem_planes = 1, |
73 | .comp_planes = 1, |
74 | .flags = MXC_JPEG_FMT_TYPE_ENC, |
75 | }, |
76 | { |
77 | .name = "BGR" , /*BGR packed format*/ |
78 | .fourcc = V4L2_PIX_FMT_BGR24, |
79 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, |
80 | .nc = 3, |
81 | .depth = 24, |
82 | .mem_planes = 1, |
83 | .comp_planes = 1, |
84 | .h_align = 3, |
85 | .v_align = 3, |
86 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
87 | .precision = 8, |
88 | .is_rgb = 1, |
89 | }, |
90 | { |
91 | .name = "BGR 12bit" , /*12-bit BGR packed format*/ |
92 | .fourcc = V4L2_PIX_FMT_BGR48_12, |
93 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, |
94 | .nc = 3, |
95 | .depth = 36, |
96 | .mem_planes = 1, |
97 | .comp_planes = 1, |
98 | .h_align = 3, |
99 | .v_align = 3, |
100 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
101 | .precision = 12, |
102 | .is_rgb = 1, |
103 | }, |
104 | { |
105 | .name = "ABGR" , /* ABGR packed format */ |
106 | .fourcc = V4L2_PIX_FMT_ABGR32, |
107 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, |
108 | .nc = 4, |
109 | .depth = 32, |
110 | .mem_planes = 1, |
111 | .comp_planes = 1, |
112 | .h_align = 3, |
113 | .v_align = 3, |
114 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
115 | .precision = 8, |
116 | .is_rgb = 1, |
117 | }, |
118 | { |
119 | .name = "ABGR 12bit" , /* 12-bit ABGR packed format */ |
120 | .fourcc = V4L2_PIX_FMT_ABGR64_12, |
121 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, |
122 | .nc = 4, |
123 | .depth = 48, |
124 | .mem_planes = 1, |
125 | .comp_planes = 1, |
126 | .h_align = 3, |
127 | .v_align = 3, |
128 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
129 | .precision = 12, |
130 | .is_rgb = 1, |
131 | }, |
132 | { |
133 | .name = "YUV420" , /* 1st plane = Y, 2nd plane = UV */ |
134 | .fourcc = V4L2_PIX_FMT_NV12M, |
135 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
136 | .nc = 3, |
137 | .depth = 12, /* 6 bytes (4Y + UV) for 4 pixels */ |
138 | .mem_planes = 2, |
139 | .comp_planes = 2, /* 1 plane Y, 1 plane UV interleaved */ |
140 | .h_align = 4, |
141 | .v_align = 4, |
142 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
143 | .precision = 8, |
144 | }, |
145 | { |
146 | .name = "YUV420" , /* 1st plane = Y, 2nd plane = UV */ |
147 | .fourcc = V4L2_PIX_FMT_NV12, |
148 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
149 | .nc = 3, |
150 | .depth = 12, /* 6 bytes (4Y + UV) for 4 pixels */ |
151 | .mem_planes = 1, |
152 | .comp_planes = 2, /* 1 plane Y, 1 plane UV interleaved */ |
153 | .h_align = 4, |
154 | .v_align = 4, |
155 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
156 | .precision = 8, |
157 | }, |
158 | { |
159 | .name = "YUV420 12bit" , /* 1st plane = Y, 2nd plane = UV */ |
160 | .fourcc = V4L2_PIX_FMT_P012M, |
161 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
162 | .nc = 3, |
163 | .depth = 18, /* 6 x 12 bits (4Y + UV) for 4 pixels */ |
164 | .mem_planes = 2, |
165 | .comp_planes = 2, /* 1 plane Y, 1 plane UV interleaved */ |
166 | .h_align = 4, |
167 | .v_align = 4, |
168 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
169 | .precision = 12, |
170 | }, |
171 | { |
172 | .name = "YUV420 12bit" , /* 1st plane = Y, 2nd plane = UV */ |
173 | .fourcc = V4L2_PIX_FMT_P012, |
174 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
175 | .nc = 3, |
176 | .depth = 18, /* 6 x 12 bits (4Y + UV) for 4 pixels */ |
177 | .mem_planes = 1, |
178 | .comp_planes = 2, /* 1 plane Y, 1 plane UV interleaved */ |
179 | .h_align = 4, |
180 | .v_align = 4, |
181 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
182 | .precision = 12, |
183 | }, |
184 | { |
185 | .name = "YUV422" , /* YUYV */ |
186 | .fourcc = V4L2_PIX_FMT_YUYV, |
187 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, |
188 | .nc = 3, |
189 | .depth = 16, |
190 | .mem_planes = 1, |
191 | .comp_planes = 1, |
192 | .h_align = 4, |
193 | .v_align = 3, |
194 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
195 | .precision = 8, |
196 | }, |
197 | { |
198 | .name = "YUV422 12bit" , /* YUYV */ |
199 | .fourcc = V4L2_PIX_FMT_Y212, |
200 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422, |
201 | .nc = 3, |
202 | .depth = 24, |
203 | .mem_planes = 1, |
204 | .comp_planes = 1, |
205 | .h_align = 4, |
206 | .v_align = 3, |
207 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
208 | .precision = 12, |
209 | }, |
210 | { |
211 | .name = "YUV444" , /* YUVYUV */ |
212 | .fourcc = V4L2_PIX_FMT_YUV24, |
213 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, |
214 | .nc = 3, |
215 | .depth = 24, |
216 | .mem_planes = 1, |
217 | .comp_planes = 1, |
218 | .h_align = 3, |
219 | .v_align = 3, |
220 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
221 | .precision = 8, |
222 | }, |
223 | { |
224 | .name = "YUV444 12bit" , /* YUVYUV */ |
225 | .fourcc = V4L2_PIX_FMT_YUV48_12, |
226 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444, |
227 | .nc = 3, |
228 | .depth = 36, |
229 | .mem_planes = 1, |
230 | .comp_planes = 1, |
231 | .h_align = 3, |
232 | .v_align = 3, |
233 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
234 | .precision = 12, |
235 | }, |
236 | { |
237 | .name = "Gray" , /* Gray (Y8/Y12) or Single Comp */ |
238 | .fourcc = V4L2_PIX_FMT_GREY, |
239 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, |
240 | .nc = 1, |
241 | .depth = 8, |
242 | .mem_planes = 1, |
243 | .comp_planes = 1, |
244 | .h_align = 3, |
245 | .v_align = 3, |
246 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
247 | .precision = 8, |
248 | }, |
249 | { |
250 | .name = "Gray 12bit" , /* Gray (Y8/Y12) or Single Comp */ |
251 | .fourcc = V4L2_PIX_FMT_Y012, |
252 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, |
253 | .nc = 1, |
254 | .depth = 12, |
255 | .mem_planes = 1, |
256 | .comp_planes = 1, |
257 | .h_align = 3, |
258 | .v_align = 3, |
259 | .flags = MXC_JPEG_FMT_TYPE_RAW, |
260 | .precision = 12, |
261 | }, |
262 | }; |
263 | |
264 | #define MXC_JPEG_NUM_FORMATS ARRAY_SIZE(mxc_formats) |
265 | |
266 | static const int mxc_decode_mode = MXC_JPEG_DECODE; |
267 | static const int mxc_encode_mode = MXC_JPEG_ENCODE; |
268 | |
269 | static const struct of_device_id mxc_jpeg_match[] = { |
270 | { |
271 | .compatible = "nxp,imx8qxp-jpgdec" , |
272 | .data = &mxc_decode_mode, |
273 | }, |
274 | { |
275 | .compatible = "nxp,imx8qxp-jpgenc" , |
276 | .data = &mxc_encode_mode, |
277 | }, |
278 | { }, |
279 | }; |
280 | |
281 | /* |
282 | * default configuration stream, 64x64 yuv422 |
283 | * split by JPEG marker, so it's easier to modify & use |
284 | */ |
285 | static const unsigned char jpeg_soi[] = { |
286 | 0xFF, 0xD8 |
287 | }; |
288 | |
289 | static const unsigned char jpeg_app0[] = { |
290 | 0xFF, 0xE0, |
291 | 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, |
292 | 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, |
293 | 0x00, 0x00 |
294 | }; |
295 | |
296 | static const unsigned char jpeg_app14[] = { |
297 | 0xFF, 0xEE, |
298 | 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, |
299 | 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00 |
300 | }; |
301 | |
302 | static const unsigned char jpeg_dqt[] = { |
303 | 0xFF, 0xDB, |
304 | 0x00, 0x84, 0x00, 0x10, 0x0B, 0x0C, 0x0E, |
305 | 0x0C, 0x0A, 0x10, 0x0E, 0x0D, 0x0E, 0x12, |
306 | 0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18, |
307 | 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1D, |
308 | 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33, |
309 | 0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, |
310 | 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, |
311 | 0x51, 0x57, 0x5F, 0x62, 0x67, 0x68, 0x67, |
312 | 0x3E, 0x4D, 0x71, 0x79, 0x70, 0x64, 0x78, |
313 | 0x5C, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, |
314 | 0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 0x1A, |
315 | 0x2F, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, |
316 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, |
317 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, |
318 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, |
319 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, |
320 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, |
321 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, |
322 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 |
323 | }; |
324 | |
325 | static const unsigned char jpeg_dqt_extseq[] = { |
326 | 0xFF, 0xDB, |
327 | 0x01, 0x04, |
328 | 0x10, |
329 | 0x00, 0x80, 0x00, 0x58, 0x00, 0x60, 0x00, 0x70, |
330 | 0x00, 0x60, 0x00, 0x50, 0x00, 0x80, 0x00, 0x70, |
331 | 0x00, 0x68, 0x00, 0x70, 0x00, 0x90, 0x00, 0x88, |
332 | 0x00, 0x80, 0x00, 0x98, 0x00, 0xC0, 0x01, 0x40, |
333 | 0x00, 0xD0, 0x00, 0xC0, 0x00, 0xB0, 0x00, 0xB0, |
334 | 0x00, 0xC0, 0x01, 0x88, 0x01, 0x18, 0x01, 0x28, |
335 | 0x00, 0xE8, 0x01, 0x40, 0x01, 0xD0, 0x01, 0x98, |
336 | 0x01, 0xE8, 0x01, 0xE0, 0x01, 0xC8, 0x01, 0x98, |
337 | 0x01, 0xC0, 0x01, 0xB8, 0x02, 0x00, 0x02, 0x40, |
338 | 0x02, 0xE0, 0x02, 0x70, 0x02, 0x00, 0x02, 0x20, |
339 | 0x02, 0xB8, 0x02, 0x28, 0x01, 0xB8, 0x01, 0xC0, |
340 | 0x02, 0x80, 0x03, 0x68, 0x02, 0x88, 0x02, 0xB8, |
341 | 0x02, 0xF8, 0x03, 0x10, 0x03, 0x38, 0x03, 0x40, |
342 | 0x03, 0x38, 0x01, 0xF0, 0x02, 0x68, 0x03, 0x88, |
343 | 0x03, 0xC8, 0x03, 0x80, 0x03, 0x20, 0x03, 0xC0, |
344 | 0x02, 0xE0, 0x03, 0x28, 0x03, 0x38, 0x03, 0x18, |
345 | 0x11, |
346 | 0x00, 0x88, 0x00, 0x90, 0x00, 0x90, 0x00, 0xC0, |
347 | 0x00, 0xA8, 0x00, 0xC0, 0x01, 0x78, 0x00, 0xD0, |
348 | 0x00, 0xD0, 0x01, 0x78, 0x03, 0x18, 0x02, 0x10, |
349 | 0x01, 0xC0, 0x02, 0x10, 0x03, 0x18, 0x03, 0x18, |
350 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
351 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
352 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
353 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
354 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
355 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
356 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
357 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
358 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
359 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
360 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
361 | 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, |
362 | }; |
363 | |
364 | static const unsigned char jpeg_sof_maximal[] = { |
365 | 0xFF, 0xC0, |
366 | 0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40, |
367 | 0x04, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, |
368 | 0x03, 0x11, 0x01, 0x04, 0x11, 0x01 |
369 | }; |
370 | |
371 | static const unsigned char jpeg_sof_extseq[] = { |
372 | 0xFF, 0xC1, |
373 | 0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40, |
374 | 0x04, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, |
375 | 0x03, 0x11, 0x01, 0x04, 0x11, 0x01 |
376 | }; |
377 | |
378 | static const unsigned char jpeg_dht[] = { |
379 | 0xFF, 0xC4, |
380 | 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, |
381 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, |
382 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
383 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
384 | 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, |
385 | 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, |
386 | 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, |
387 | 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, |
388 | 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, |
389 | 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, |
390 | 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, |
391 | 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, |
392 | 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, |
393 | 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, |
394 | 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, |
395 | 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, |
396 | 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
397 | 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, |
398 | 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, |
399 | 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, |
400 | 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, |
401 | 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, |
402 | 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, |
403 | 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, |
404 | 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, |
405 | 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, |
406 | 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, |
407 | 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, |
408 | 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, |
409 | 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, |
410 | 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, |
411 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, |
412 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, |
413 | 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, |
414 | 0x0B, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, |
415 | 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, |
416 | 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, |
417 | 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, |
418 | 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, |
419 | 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, |
420 | 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, |
421 | 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, |
422 | 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, |
423 | 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, |
424 | 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, |
425 | 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, |
426 | 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, |
427 | 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
428 | 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, |
429 | 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, |
430 | 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, |
431 | 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, |
432 | 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, |
433 | 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, |
434 | 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, |
435 | 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, |
436 | 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, |
437 | 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, |
438 | 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, |
439 | 0xF6, 0xF7, 0xF8, 0xF9, 0xFA |
440 | }; |
441 | |
442 | static const unsigned char jpeg_dht_extseq[] = { |
443 | 0xFF, 0xC4, |
444 | 0x02, 0x2a, 0x00, 0x00, 0x01, 0x05, 0x01, |
445 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
446 | 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, |
447 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
448 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
449 | 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, |
450 | 0x04, 0x03, 0x05, 0x05, 0x02, 0x03, 0x02, |
451 | 0x00, 0x00, 0xbf, 0x01, 0x02, 0x03, 0x00, |
452 | 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, |
453 | 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, |
454 | 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, |
455 | 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, |
456 | 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, |
457 | 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, |
458 | 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, |
459 | 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, |
460 | 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, |
461 | 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, |
462 | 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, |
463 | 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, |
464 | 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, |
465 | 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, |
466 | 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, |
467 | 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, |
468 | 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, |
469 | 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, |
470 | 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, |
471 | 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, |
472 | 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, |
473 | 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, |
474 | 0xf7, 0xf8, 0xf9, 0xfa, 0x0b, 0x0c, 0x0d, |
475 | 0x0e, 0x1b, 0x1c, 0x1d, 0x1e, 0x2b, 0x2c, |
476 | 0x2d, 0x2e, 0x3b, 0x3c, 0x3d, 0x3e, 0x4b, |
477 | 0x4c, 0x4d, 0x4e, 0x5b, 0x5c, 0x5d, 0x5e, |
478 | 0x6b, 0x6c, 0x6d, 0x6e, 0x7b, 0x7c, 0x7d, |
479 | 0x7e, 0x8b, 0x8c, 0x8d, 0x8e, 0x9b, 0x9c, |
480 | 0x9d, 0x9e, 0xab, 0xac, 0xad, 0xae, 0xbb, |
481 | 0xbc, 0xbd, 0xbe, 0xcb, 0xcc, 0xcd, 0xce, |
482 | 0xdb, 0xdc, 0xdd, 0xde, 0xeb, 0xec, 0xed, |
483 | 0xee, 0xfb, 0xfc, 0xfd, 0xfe, 0x01, 0x00, |
484 | 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, |
485 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, |
486 | 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, |
487 | 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, |
488 | 0x0d, 0x0e, 0x0f, 0x11, 0x00, 0x02, 0x01, |
489 | 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, |
490 | 0x02, 0x03, 0x02, 0x00, 0x00, 0xbf, 0x01, |
491 | 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, |
492 | 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, |
493 | 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, |
494 | 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, |
495 | 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, |
496 | 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, |
497 | 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, |
498 | 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, |
499 | 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, |
500 | 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
501 | 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, |
502 | 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, |
503 | 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, |
504 | 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, |
505 | 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, |
506 | 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, |
507 | 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, |
508 | 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, |
509 | 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, |
510 | 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, |
511 | 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, |
512 | 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, |
513 | 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, |
514 | 0x0b, 0x0c, 0x0d, 0x0e, 0x1b, 0x1c, 0x1d, |
515 | 0x1e, 0x2b, 0x2c, 0x2d, 0x2e, 0x3b, 0x3c, |
516 | 0x3d, 0x3e, 0x4b, 0x4c, 0x4d, 0x4e, 0x5b, |
517 | 0x5c, 0x5d, 0x5e, 0x6b, 0x6c, 0x6d, 0x6e, |
518 | 0x7b, 0x7c, 0x7d, 0x7e, 0x8b, 0x8c, 0x8d, |
519 | 0x8e, 0x9b, 0x9c, 0x9d, 0x9e, 0xab, 0xac, |
520 | 0xad, 0xae, 0xbb, 0xbc, 0xbd, 0xbe, 0xcb, |
521 | 0xcc, 0xcd, 0xce, 0xdb, 0xdc, 0xdd, 0xde, |
522 | 0xeb, 0xec, 0xed, 0xee, 0xfb, 0xfc, 0xfd, |
523 | 0xfe, |
524 | }; |
525 | |
526 | static const unsigned char jpeg_dri[] = { |
527 | 0xFF, 0xDD, |
528 | 0x00, 0x04, 0x00, 0x20 |
529 | }; |
530 | |
531 | static const unsigned char jpeg_sos_maximal[] = { |
532 | 0xFF, 0xDA, |
533 | 0x00, 0x0C, 0x04, 0x01, 0x00, 0x02, 0x11, 0x03, |
534 | 0x11, 0x04, 0x11, 0x00, 0x3F, 0x00 |
535 | }; |
536 | |
537 | static const unsigned char jpeg_image_red[] = { |
538 | 0xFC, 0x5F, 0xA2, 0xBF, 0xCA, 0x73, 0xFE, 0xFE, |
539 | 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, |
540 | 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, |
541 | 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, |
542 | 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, |
543 | 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, |
544 | 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, |
545 | 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, |
546 | 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, |
547 | 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, |
548 | 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00 |
549 | }; |
550 | |
551 | static const unsigned char jpeg_eoi[] = { |
552 | 0xFF, 0xD9 |
553 | }; |
554 | |
555 | struct mxc_jpeg_src_buf { |
556 | /* common v4l buffer stuff -- must be first */ |
557 | struct vb2_v4l2_buffer b; |
558 | struct list_head list; |
559 | |
560 | /* mxc-jpeg specific */ |
561 | bool dht_needed; |
562 | bool jpeg_parse_error; |
563 | const struct mxc_jpeg_fmt *fmt; |
564 | int w; |
565 | int h; |
566 | }; |
567 | |
568 | static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb) |
569 | { |
570 | return container_of(to_vb2_v4l2_buffer(vb), |
571 | struct mxc_jpeg_src_buf, b); |
572 | } |
573 | |
574 | static unsigned int debug; |
575 | module_param(debug, int, 0644); |
576 | MODULE_PARM_DESC(debug, "Debug level (0-3)" ); |
577 | |
578 | static unsigned int hw_timeout = 2000; |
579 | module_param(hw_timeout, int, 0644); |
580 | MODULE_PARM_DESC(hw_timeout, "MXC JPEG hw timeout, the number of milliseconds" ); |
581 | |
582 | static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision); |
583 | static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q); |
584 | |
585 | static void _bswap16(u16 *a) |
586 | { |
587 | *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8); |
588 | } |
589 | |
590 | static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf, |
591 | unsigned long len) |
592 | { |
593 | unsigned int plane_no; |
594 | u32 dma_addr; |
595 | void *vaddr; |
596 | unsigned long payload; |
597 | |
598 | if (debug < 3) |
599 | return; |
600 | |
601 | for (plane_no = 0; plane_no < buf->num_planes; plane_no++) { |
602 | payload = vb2_get_plane_payload(vb: buf, plane_no); |
603 | if (len == 0) |
604 | len = payload; |
605 | dma_addr = vb2_dma_contig_plane_dma_addr(vb: buf, plane_no); |
606 | vaddr = vb2_plane_vaddr(vb: buf, plane_no); |
607 | v4l2_dbg(3, debug, &jpeg->v4l2_dev, |
608 | "plane %d (vaddr=%p dma_addr=%x payload=%ld):" , |
609 | plane_no, vaddr, dma_addr, payload); |
610 | print_hex_dump(KERN_DEBUG, prefix_str: "" , prefix_type: DUMP_PREFIX_OFFSET, rowsize: 32, groupsize: 1, |
611 | buf: vaddr, len, ascii: false); |
612 | } |
613 | } |
614 | |
615 | static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh) |
616 | { |
617 | return container_of(fh, struct mxc_jpeg_ctx, fh); |
618 | } |
619 | |
620 | static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n, |
621 | struct v4l2_fmtdesc *f, u32 type) |
622 | { |
623 | int i, num = 0; |
624 | |
625 | for (i = 0; i < n; ++i) { |
626 | if (mxc_formats[i].flags == type) { |
627 | /* index-th format of searched type found ? */ |
628 | if (num == f->index) |
629 | break; |
630 | /* Correct type but haven't reached our index yet, |
631 | * just increment per-type index |
632 | */ |
633 | ++num; |
634 | } |
635 | } |
636 | |
637 | /* Format not found */ |
638 | if (i >= n) |
639 | return -EINVAL; |
640 | |
641 | f->pixelformat = mxc_formats[i].fourcc; |
642 | |
643 | return 0; |
644 | } |
645 | |
646 | static const struct mxc_jpeg_fmt *mxc_jpeg_find_format(u32 pixelformat) |
647 | { |
648 | unsigned int k; |
649 | |
650 | for (k = 0; k < MXC_JPEG_NUM_FORMATS; k++) { |
651 | const struct mxc_jpeg_fmt *fmt = &mxc_formats[k]; |
652 | |
653 | if (fmt->fourcc == pixelformat) |
654 | return fmt; |
655 | } |
656 | return NULL; |
657 | } |
658 | |
659 | static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc) |
660 | { |
661 | switch (fourcc) { |
662 | case V4L2_PIX_FMT_GREY: |
663 | case V4L2_PIX_FMT_Y012: |
664 | return MXC_JPEG_GRAY; |
665 | case V4L2_PIX_FMT_YUYV: |
666 | case V4L2_PIX_FMT_Y212: |
667 | return MXC_JPEG_YUV422; |
668 | case V4L2_PIX_FMT_NV12: |
669 | case V4L2_PIX_FMT_NV12M: |
670 | case V4L2_PIX_FMT_P012: |
671 | case V4L2_PIX_FMT_P012M: |
672 | return MXC_JPEG_YUV420; |
673 | case V4L2_PIX_FMT_YUV24: |
674 | case V4L2_PIX_FMT_YUV48_12: |
675 | return MXC_JPEG_YUV444; |
676 | case V4L2_PIX_FMT_BGR24: |
677 | case V4L2_PIX_FMT_BGR48_12: |
678 | return MXC_JPEG_BGR; |
679 | case V4L2_PIX_FMT_ABGR32: |
680 | case V4L2_PIX_FMT_ABGR64_12: |
681 | return MXC_JPEG_ABGR; |
682 | default: |
683 | return MXC_JPEG_INVALID; |
684 | } |
685 | } |
686 | |
687 | static struct mxc_jpeg_q_data *mxc_jpeg_get_q_data(struct mxc_jpeg_ctx *ctx, |
688 | enum v4l2_buf_type type) |
689 | { |
690 | if (V4L2_TYPE_IS_OUTPUT(type)) |
691 | return &ctx->out_q; |
692 | return &ctx->cap_q; |
693 | } |
694 | |
695 | static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc, |
696 | struct vb2_buffer *raw_buf, |
697 | struct vb2_buffer *jpeg_buf, int offset) |
698 | { |
699 | int img_fmt = desc->stm_ctrl & STM_CTRL_IMAGE_FORMAT_MASK; |
700 | struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q: raw_buf->vb2_queue); |
701 | struct mxc_jpeg_q_data *q_data; |
702 | |
703 | q_data = mxc_jpeg_get_q_data(ctx, type: raw_buf->type); |
704 | desc->buf_base0 = vb2_dma_contig_plane_dma_addr(vb: raw_buf, plane_no: 0); |
705 | desc->buf_base1 = 0; |
706 | if (img_fmt == STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV420)) { |
707 | if (raw_buf->num_planes == 2) |
708 | desc->buf_base1 = vb2_dma_contig_plane_dma_addr(vb: raw_buf, plane_no: 1); |
709 | else |
710 | desc->buf_base1 = desc->buf_base0 + q_data->sizeimage[0]; |
711 | } |
712 | desc->stm_bufbase = vb2_dma_contig_plane_dma_addr(vb: jpeg_buf, plane_no: 0) + |
713 | offset; |
714 | } |
715 | |
716 | static bool mxc_jpeg_is_extended_sequential(const struct mxc_jpeg_fmt *fmt) |
717 | { |
718 | if (!fmt || !(fmt->flags & MXC_JPEG_FMT_TYPE_RAW)) |
719 | return false; |
720 | |
721 | if (fmt->precision > 8) |
722 | return true; |
723 | |
724 | return false; |
725 | } |
726 | |
727 | static void notify_eos(struct mxc_jpeg_ctx *ctx) |
728 | { |
729 | const struct v4l2_event ev = { |
730 | .type = V4L2_EVENT_EOS |
731 | }; |
732 | |
733 | dev_dbg(ctx->mxc_jpeg->dev, "Notify app event EOS reached" ); |
734 | v4l2_event_queue_fh(fh: &ctx->fh, ev: &ev); |
735 | } |
736 | |
737 | static void notify_src_chg(struct mxc_jpeg_ctx *ctx) |
738 | { |
739 | const struct v4l2_event ev = { |
740 | .type = V4L2_EVENT_SOURCE_CHANGE, |
741 | .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, |
742 | }; |
743 | |
744 | dev_dbg(ctx->mxc_jpeg->dev, "Notify app event SRC_CH_RESOLUTION" ); |
745 | v4l2_event_queue_fh(fh: &ctx->fh, ev: &ev); |
746 | } |
747 | |
748 | static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data) |
749 | { |
750 | if (!slot_data->used) |
751 | return slot_data->slot; |
752 | return -1; |
753 | } |
754 | |
755 | static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg) |
756 | { |
757 | struct mxc_jpeg_desc *desc; |
758 | struct mxc_jpeg_desc *cfg_desc; |
759 | void *cfg_stm; |
760 | |
761 | if (jpeg->slot_data.desc) |
762 | goto skip_alloc; /* already allocated, reuse it */ |
763 | |
764 | /* allocate descriptor for decoding/encoding phase */ |
765 | desc = dma_alloc_coherent(dev: jpeg->dev, |
766 | size: sizeof(struct mxc_jpeg_desc), |
767 | dma_handle: &jpeg->slot_data.desc_handle, |
768 | GFP_ATOMIC); |
769 | if (!desc) |
770 | goto err; |
771 | jpeg->slot_data.desc = desc; |
772 | |
773 | /* allocate descriptor for configuration phase (encoder only) */ |
774 | cfg_desc = dma_alloc_coherent(dev: jpeg->dev, |
775 | size: sizeof(struct mxc_jpeg_desc), |
776 | dma_handle: &jpeg->slot_data.cfg_desc_handle, |
777 | GFP_ATOMIC); |
778 | if (!cfg_desc) |
779 | goto err; |
780 | jpeg->slot_data.cfg_desc = cfg_desc; |
781 | |
782 | /* allocate configuration stream */ |
783 | cfg_stm = dma_alloc_coherent(dev: jpeg->dev, |
784 | MXC_JPEG_MAX_CFG_STREAM, |
785 | dma_handle: &jpeg->slot_data.cfg_stream_handle, |
786 | GFP_ATOMIC); |
787 | if (!cfg_stm) |
788 | goto err; |
789 | jpeg->slot_data.cfg_stream_vaddr = cfg_stm; |
790 | |
791 | skip_alloc: |
792 | jpeg->slot_data.used = true; |
793 | |
794 | return true; |
795 | err: |
796 | dev_err(jpeg->dev, "Could not allocate descriptors for slot %d" , jpeg->slot_data.slot); |
797 | |
798 | return false; |
799 | } |
800 | |
801 | static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg) |
802 | { |
803 | /* free descriptor for decoding/encoding phase */ |
804 | dma_free_coherent(dev: jpeg->dev, size: sizeof(struct mxc_jpeg_desc), |
805 | cpu_addr: jpeg->slot_data.desc, |
806 | dma_handle: jpeg->slot_data.desc_handle); |
807 | |
808 | /* free descriptor for encoder configuration phase / decoder DHT */ |
809 | dma_free_coherent(dev: jpeg->dev, size: sizeof(struct mxc_jpeg_desc), |
810 | cpu_addr: jpeg->slot_data.cfg_desc, |
811 | dma_handle: jpeg->slot_data.cfg_desc_handle); |
812 | |
813 | /* free configuration stream */ |
814 | dma_free_coherent(dev: jpeg->dev, MXC_JPEG_MAX_CFG_STREAM, |
815 | cpu_addr: jpeg->slot_data.cfg_stream_vaddr, |
816 | dma_handle: jpeg->slot_data.cfg_stream_handle); |
817 | |
818 | jpeg->slot_data.used = false; |
819 | } |
820 | |
821 | static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx, |
822 | struct vb2_v4l2_buffer *src_buf, |
823 | struct vb2_v4l2_buffer *dst_buf) |
824 | { |
825 | if (v4l2_m2m_is_last_draining_src_buf(m2m_ctx: ctx->fh.m2m_ctx, vbuf: src_buf)) { |
826 | dst_buf->flags |= V4L2_BUF_FLAG_LAST; |
827 | v4l2_m2m_mark_stopped(m2m_ctx: ctx->fh.m2m_ctx); |
828 | notify_eos(ctx); |
829 | ctx->header_parsed = false; |
830 | } |
831 | } |
832 | |
833 | static void mxc_jpeg_job_finish(struct mxc_jpeg_ctx *ctx, enum vb2_buffer_state state, bool reset) |
834 | { |
835 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
836 | void __iomem *reg = jpeg->base_reg; |
837 | struct vb2_v4l2_buffer *src_buf, *dst_buf; |
838 | |
839 | dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx: ctx->fh.m2m_ctx); |
840 | src_buf = v4l2_m2m_next_src_buf(m2m_ctx: ctx->fh.m2m_ctx); |
841 | mxc_jpeg_check_and_set_last_buffer(ctx, src_buf, dst_buf); |
842 | v4l2_m2m_src_buf_remove(m2m_ctx: ctx->fh.m2m_ctx); |
843 | v4l2_m2m_dst_buf_remove(m2m_ctx: ctx->fh.m2m_ctx); |
844 | v4l2_m2m_buf_done(buf: src_buf, state); |
845 | v4l2_m2m_buf_done(buf: dst_buf, state); |
846 | |
847 | mxc_jpeg_disable_irq(reg, slot: ctx->slot); |
848 | jpeg->slot_data.used = false; |
849 | if (reset) |
850 | mxc_jpeg_sw_reset(reg); |
851 | } |
852 | |
853 | static u32 mxc_jpeg_get_plane_size(struct mxc_jpeg_q_data *q_data, u32 plane_no) |
854 | { |
855 | const struct mxc_jpeg_fmt *fmt = q_data->fmt; |
856 | u32 size; |
857 | int i; |
858 | |
859 | if (plane_no >= fmt->mem_planes) |
860 | return 0; |
861 | |
862 | if (fmt->mem_planes == fmt->comp_planes) |
863 | return q_data->sizeimage[plane_no]; |
864 | |
865 | if (plane_no < fmt->mem_planes - 1) |
866 | return q_data->sizeimage[plane_no]; |
867 | |
868 | size = q_data->sizeimage[fmt->mem_planes - 1]; |
869 | |
870 | /* Should be impossible given mxc_formats. */ |
871 | if (WARN_ON_ONCE(fmt->comp_planes > ARRAY_SIZE(q_data->sizeimage))) |
872 | return size; |
873 | |
874 | for (i = fmt->mem_planes; i < fmt->comp_planes; i++) |
875 | size += q_data->sizeimage[i]; |
876 | |
877 | return size; |
878 | } |
879 | |
880 | static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) |
881 | { |
882 | struct mxc_jpeg_dev *jpeg = priv; |
883 | struct mxc_jpeg_ctx *ctx; |
884 | void __iomem *reg = jpeg->base_reg; |
885 | struct device *dev = jpeg->dev; |
886 | struct vb2_v4l2_buffer *src_buf, *dst_buf; |
887 | struct mxc_jpeg_src_buf *jpeg_src_buf; |
888 | enum vb2_buffer_state buf_state; |
889 | u32 dec_ret, com_status; |
890 | unsigned long payload; |
891 | struct mxc_jpeg_q_data *q_data; |
892 | enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
893 | unsigned int slot; |
894 | |
895 | spin_lock(lock: &jpeg->hw_lock); |
896 | |
897 | com_status = readl(addr: reg + COM_STATUS); |
898 | slot = COM_STATUS_CUR_SLOT(com_status); |
899 | dev_dbg(dev, "Irq %d on slot %d.\n" , irq, slot); |
900 | |
901 | ctx = v4l2_m2m_get_curr_priv(m2m_dev: jpeg->m2m_dev); |
902 | if (WARN_ON(!ctx)) |
903 | goto job_unlock; |
904 | |
905 | if (slot != ctx->slot) { |
906 | /* TODO investigate when adding multi-instance support */ |
907 | dev_warn(dev, "IRQ slot %d != context slot %d.\n" , |
908 | slot, ctx->slot); |
909 | goto job_unlock; |
910 | } |
911 | |
912 | if (!jpeg->slot_data.used) |
913 | goto job_unlock; |
914 | |
915 | dec_ret = readl(addr: reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); |
916 | writel(val: dec_ret, addr: reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); /* w1c */ |
917 | |
918 | dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx: ctx->fh.m2m_ctx); |
919 | src_buf = v4l2_m2m_next_src_buf(m2m_ctx: ctx->fh.m2m_ctx); |
920 | if (!dst_buf || !src_buf) { |
921 | dev_err(dev, "No source or destination buffer.\n" ); |
922 | goto job_unlock; |
923 | } |
924 | jpeg_src_buf = vb2_to_mxc_buf(vb: &src_buf->vb2_buf); |
925 | |
926 | if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) { |
927 | u32 ret = readl(addr: reg + CAST_STATUS12); |
928 | |
929 | dev_err(dev, "Encoder/decoder error, dec_ret = 0x%08x, status=0x%08x" , |
930 | dec_ret, ret); |
931 | mxc_jpeg_clr_desc(reg, slot); |
932 | mxc_jpeg_sw_reset(reg); |
933 | buf_state = VB2_BUF_STATE_ERROR; |
934 | goto buffers_done; |
935 | } |
936 | |
937 | if (!(dec_ret & SLOT_STATUS_FRMDONE)) |
938 | goto job_unlock; |
939 | |
940 | if (jpeg->mode == MXC_JPEG_ENCODE && |
941 | ctx->enc_state == MXC_JPEG_ENC_CONF) { |
942 | q_data = mxc_jpeg_get_q_data(ctx, type: V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); |
943 | ctx->enc_state = MXC_JPEG_ENCODING; |
944 | dev_dbg(dev, "Encoder config finished. Start encoding...\n" ); |
945 | mxc_jpeg_enc_set_quality(dev, reg, quality: ctx->jpeg_quality); |
946 | mxc_jpeg_enc_mode_go(dev, reg, extseq: mxc_jpeg_is_extended_sequential(fmt: q_data->fmt)); |
947 | goto job_unlock; |
948 | } |
949 | if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed) { |
950 | jpeg_src_buf->dht_needed = false; |
951 | dev_dbg(dev, "Decoder DHT cfg finished. Start decoding...\n" ); |
952 | goto job_unlock; |
953 | } |
954 | |
955 | if (jpeg->mode == MXC_JPEG_ENCODE) { |
956 | payload = readl(addr: reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR)); |
957 | vb2_set_plane_payload(vb: &dst_buf->vb2_buf, plane_no: 0, size: payload); |
958 | dev_dbg(dev, "Encoding finished, payload size: %ld\n" , |
959 | payload); |
960 | } else { |
961 | q_data = mxc_jpeg_get_q_data(ctx, type: cap_type); |
962 | payload = mxc_jpeg_get_plane_size(q_data, plane_no: 0); |
963 | vb2_set_plane_payload(vb: &dst_buf->vb2_buf, plane_no: 0, size: payload); |
964 | vb2_set_plane_payload(vb: &dst_buf->vb2_buf, plane_no: 1, size: 0); |
965 | if (q_data->fmt->mem_planes == 2) { |
966 | payload = mxc_jpeg_get_plane_size(q_data, plane_no: 1); |
967 | vb2_set_plane_payload(vb: &dst_buf->vb2_buf, plane_no: 1, size: payload); |
968 | } |
969 | dev_dbg(dev, "Decoding finished, payload size: %ld + %ld\n" , |
970 | vb2_get_plane_payload(&dst_buf->vb2_buf, 0), |
971 | vb2_get_plane_payload(&dst_buf->vb2_buf, 1)); |
972 | } |
973 | |
974 | /* short preview of the results */ |
975 | dev_dbg(dev, "src_buf preview: " ); |
976 | print_mxc_buf(jpeg, buf: &src_buf->vb2_buf, len: 32); |
977 | dev_dbg(dev, "dst_buf preview: " ); |
978 | print_mxc_buf(jpeg, buf: &dst_buf->vb2_buf, len: 32); |
979 | buf_state = VB2_BUF_STATE_DONE; |
980 | |
981 | buffers_done: |
982 | mxc_jpeg_job_finish(ctx, state: buf_state, reset: false); |
983 | spin_unlock(lock: &jpeg->hw_lock); |
984 | cancel_delayed_work(dwork: &ctx->task_timer); |
985 | v4l2_m2m_job_finish(m2m_dev: jpeg->m2m_dev, m2m_ctx: ctx->fh.m2m_ctx); |
986 | return IRQ_HANDLED; |
987 | job_unlock: |
988 | spin_unlock(lock: &jpeg->hw_lock); |
989 | return IRQ_HANDLED; |
990 | } |
991 | |
992 | static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof, |
993 | u32 fourcc, |
994 | u16 w, u16 h) |
995 | { |
996 | int sof_length; |
997 | const struct mxc_jpeg_fmt *fmt = mxc_jpeg_find_format(pixelformat: fourcc); |
998 | |
999 | if (fmt) |
1000 | sof->precision = fmt->precision; |
1001 | else |
1002 | sof->precision = 8; /* TODO allow 8/12 bit precision*/ |
1003 | sof->height = h; |
1004 | _bswap16(a: &sof->height); |
1005 | sof->width = w; |
1006 | _bswap16(a: &sof->width); |
1007 | |
1008 | switch (fourcc) { |
1009 | case V4L2_PIX_FMT_NV12: |
1010 | case V4L2_PIX_FMT_NV12M: |
1011 | case V4L2_PIX_FMT_P012: |
1012 | case V4L2_PIX_FMT_P012M: |
1013 | sof->components_no = 3; |
1014 | sof->comp[0].v = 0x2; |
1015 | sof->comp[0].h = 0x2; |
1016 | break; |
1017 | case V4L2_PIX_FMT_YUYV: |
1018 | case V4L2_PIX_FMT_Y212: |
1019 | sof->components_no = 3; |
1020 | sof->comp[0].v = 0x1; |
1021 | sof->comp[0].h = 0x2; |
1022 | break; |
1023 | case V4L2_PIX_FMT_YUV24: |
1024 | case V4L2_PIX_FMT_YUV48_12: |
1025 | case V4L2_PIX_FMT_BGR24: |
1026 | case V4L2_PIX_FMT_BGR48_12: |
1027 | default: |
1028 | sof->components_no = 3; |
1029 | break; |
1030 | case V4L2_PIX_FMT_ABGR32: |
1031 | case V4L2_PIX_FMT_ABGR64_12: |
1032 | sof->components_no = 4; |
1033 | break; |
1034 | case V4L2_PIX_FMT_GREY: |
1035 | case V4L2_PIX_FMT_Y012: |
1036 | sof->components_no = 1; |
1037 | break; |
1038 | } |
1039 | sof_length = 8 + 3 * sof->components_no; |
1040 | sof->length = sof_length; |
1041 | _bswap16(a: &sof->length); |
1042 | |
1043 | return sof_length; /* not swaped */ |
1044 | } |
1045 | |
1046 | static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos, |
1047 | u32 fourcc) |
1048 | { |
1049 | int sos_length; |
1050 | u8 *sof_u8 = (u8 *)sos; |
1051 | |
1052 | switch (fourcc) { |
1053 | case V4L2_PIX_FMT_NV12: |
1054 | case V4L2_PIX_FMT_NV12M: |
1055 | case V4L2_PIX_FMT_P012: |
1056 | case V4L2_PIX_FMT_P012M: |
1057 | sos->components_no = 3; |
1058 | break; |
1059 | case V4L2_PIX_FMT_YUYV: |
1060 | case V4L2_PIX_FMT_Y212: |
1061 | sos->components_no = 3; |
1062 | break; |
1063 | case V4L2_PIX_FMT_YUV24: |
1064 | case V4L2_PIX_FMT_YUV48_12: |
1065 | case V4L2_PIX_FMT_BGR24: |
1066 | case V4L2_PIX_FMT_BGR48_12: |
1067 | default: |
1068 | sos->components_no = 3; |
1069 | break; |
1070 | case V4L2_PIX_FMT_ABGR32: |
1071 | case V4L2_PIX_FMT_ABGR64_12: |
1072 | sos->components_no = 4; |
1073 | break; |
1074 | case V4L2_PIX_FMT_GREY: |
1075 | case V4L2_PIX_FMT_Y012: |
1076 | sos->components_no = 1; |
1077 | break; |
1078 | } |
1079 | sos_length = 6 + 2 * sos->components_no; |
1080 | sos->length = sos_length; |
1081 | _bswap16(a: &sos->length); |
1082 | |
1083 | /* SOS ignorable bytes, not so ignorable after all */ |
1084 | sof_u8[sos_length - 1] = 0x0; |
1085 | sof_u8[sos_length - 2] = 0x3f; |
1086 | sof_u8[sos_length - 3] = 0x0; |
1087 | |
1088 | return sos_length; /* not swaped */ |
1089 | } |
1090 | |
1091 | static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr, |
1092 | u32 fourcc, |
1093 | u16 w, u16 h) |
1094 | { |
1095 | /* |
1096 | * There is a hardware issue that first 128 bytes of configuration data |
1097 | * can't be loaded correctly. |
1098 | * To avoid this issue, we need to write the configuration from |
1099 | * an offset which should be no less than 0x80 (128 bytes). |
1100 | */ |
1101 | unsigned int offset = 0x80; |
1102 | u8 *cfg = (u8 *)cfg_stream_vaddr; |
1103 | struct mxc_jpeg_sof *sof; |
1104 | struct mxc_jpeg_sos *sos; |
1105 | const struct mxc_jpeg_fmt *fmt = mxc_jpeg_find_format(pixelformat: fourcc); |
1106 | |
1107 | if (!fmt) |
1108 | return 0; |
1109 | |
1110 | memcpy(cfg + offset, jpeg_soi, ARRAY_SIZE(jpeg_soi)); |
1111 | offset += ARRAY_SIZE(jpeg_soi); |
1112 | |
1113 | if (fmt->is_rgb) { |
1114 | memcpy(cfg + offset, jpeg_app14, sizeof(jpeg_app14)); |
1115 | offset += sizeof(jpeg_app14); |
1116 | } else { |
1117 | memcpy(cfg + offset, jpeg_app0, sizeof(jpeg_app0)); |
1118 | offset += sizeof(jpeg_app0); |
1119 | } |
1120 | |
1121 | if (mxc_jpeg_is_extended_sequential(fmt)) { |
1122 | memcpy(cfg + offset, jpeg_dqt_extseq, sizeof(jpeg_dqt_extseq)); |
1123 | offset += sizeof(jpeg_dqt_extseq); |
1124 | |
1125 | memcpy(cfg + offset, jpeg_sof_extseq, sizeof(jpeg_sof_extseq)); |
1126 | } else { |
1127 | memcpy(cfg + offset, jpeg_dqt, sizeof(jpeg_dqt)); |
1128 | offset += sizeof(jpeg_dqt); |
1129 | |
1130 | memcpy(cfg + offset, jpeg_sof_maximal, sizeof(jpeg_sof_maximal)); |
1131 | } |
1132 | offset += 2; /* skip marker ID */ |
1133 | sof = (struct mxc_jpeg_sof *)(cfg + offset); |
1134 | offset += mxc_jpeg_fixup_sof(sof, fourcc, w, h); |
1135 | |
1136 | if (mxc_jpeg_is_extended_sequential(fmt)) { |
1137 | memcpy(cfg + offset, jpeg_dht_extseq, sizeof(jpeg_dht_extseq)); |
1138 | offset += sizeof(jpeg_dht_extseq); |
1139 | } else { |
1140 | memcpy(cfg + offset, jpeg_dht, sizeof(jpeg_dht)); |
1141 | offset += sizeof(jpeg_dht); |
1142 | } |
1143 | |
1144 | memcpy(cfg + offset, jpeg_dri, sizeof(jpeg_dri)); |
1145 | offset += sizeof(jpeg_dri); |
1146 | |
1147 | memcpy(cfg + offset, jpeg_sos_maximal, sizeof(jpeg_sos_maximal)); |
1148 | offset += 2; /* skip marker ID */ |
1149 | sos = (struct mxc_jpeg_sos *)(cfg + offset); |
1150 | offset += mxc_jpeg_fixup_sos(sos, fourcc); |
1151 | |
1152 | memcpy(cfg + offset, jpeg_image_red, sizeof(jpeg_image_red)); |
1153 | offset += sizeof(jpeg_image_red); |
1154 | |
1155 | memcpy(cfg + offset, jpeg_eoi, sizeof(jpeg_eoi)); |
1156 | offset += sizeof(jpeg_eoi); |
1157 | |
1158 | return offset; |
1159 | } |
1160 | |
1161 | static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf, |
1162 | struct mxc_jpeg_ctx *ctx, |
1163 | struct vb2_buffer *src_buf, |
1164 | struct vb2_buffer *dst_buf) |
1165 | { |
1166 | enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1167 | struct mxc_jpeg_q_data *q_data_cap; |
1168 | enum mxc_jpeg_image_format img_fmt; |
1169 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
1170 | void __iomem *reg = jpeg->base_reg; |
1171 | unsigned int slot = ctx->slot; |
1172 | struct mxc_jpeg_desc *desc = jpeg->slot_data.desc; |
1173 | struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc; |
1174 | dma_addr_t desc_handle = jpeg->slot_data.desc_handle; |
1175 | dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle; |
1176 | dma_addr_t cfg_stream_handle = jpeg->slot_data.cfg_stream_handle; |
1177 | unsigned int *cfg_size = &jpeg->slot_data.cfg_stream_size; |
1178 | void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr; |
1179 | struct mxc_jpeg_src_buf *jpeg_src_buf; |
1180 | |
1181 | jpeg_src_buf = vb2_to_mxc_buf(vb: src_buf); |
1182 | |
1183 | /* setup the decoding descriptor */ |
1184 | desc->next_descpt_ptr = 0; /* end of chain */ |
1185 | q_data_cap = mxc_jpeg_get_q_data(ctx, type: cap_type); |
1186 | desc->imgsize = q_data_cap->w_adjusted << 16 | q_data_cap->h_adjusted; |
1187 | img_fmt = mxc_jpeg_fourcc_to_imgfmt(fourcc: q_data_cap->fmt->fourcc); |
1188 | desc->stm_ctrl &= ~STM_CTRL_IMAGE_FORMAT(0xF); /* clear image format */ |
1189 | desc->stm_ctrl |= STM_CTRL_IMAGE_FORMAT(img_fmt); |
1190 | desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1); |
1191 | if (mxc_jpeg_is_extended_sequential(fmt: jpeg_src_buf->fmt)) |
1192 | desc->stm_ctrl |= STM_CTRL_PIXEL_PRECISION; |
1193 | else |
1194 | desc->stm_ctrl &= ~STM_CTRL_PIXEL_PRECISION; |
1195 | desc->line_pitch = q_data_cap->bytesperline[0]; |
1196 | mxc_jpeg_addrs(desc, raw_buf: dst_buf, jpeg_buf: src_buf, offset: 0); |
1197 | mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(src_buf, 0), 1024)); |
1198 | print_descriptor_info(dev: jpeg->dev, desc); |
1199 | |
1200 | if (!jpeg_src_buf->dht_needed) { |
1201 | /* validate the decoding descriptor */ |
1202 | mxc_jpeg_set_desc(desc: desc_handle, reg, slot); |
1203 | return; |
1204 | } |
1205 | |
1206 | /* |
1207 | * if a default huffman table is needed, use the config descriptor to |
1208 | * inject a DHT, by chaining it before the decoding descriptor |
1209 | */ |
1210 | *cfg_size = mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr, |
1211 | V4L2_PIX_FMT_YUYV, |
1212 | MXC_JPEG_MIN_WIDTH, |
1213 | MXC_JPEG_MIN_HEIGHT); |
1214 | cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN; |
1215 | cfg_desc->buf_base0 = vb2_dma_contig_plane_dma_addr(vb: dst_buf, plane_no: 0); |
1216 | cfg_desc->buf_base1 = 0; |
1217 | cfg_desc->imgsize = MXC_JPEG_MIN_WIDTH << 16; |
1218 | cfg_desc->imgsize |= MXC_JPEG_MIN_HEIGHT; |
1219 | cfg_desc->line_pitch = MXC_JPEG_MIN_WIDTH * 2; |
1220 | cfg_desc->stm_ctrl = STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV422); |
1221 | cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1); |
1222 | cfg_desc->stm_bufbase = cfg_stream_handle; |
1223 | cfg_desc->stm_bufsize = ALIGN(*cfg_size, 1024); |
1224 | print_descriptor_info(dev: jpeg->dev, desc: cfg_desc); |
1225 | |
1226 | /* validate the configuration descriptor */ |
1227 | mxc_jpeg_set_desc(desc: cfg_desc_handle, reg, slot); |
1228 | } |
1229 | |
1230 | static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf, |
1231 | struct mxc_jpeg_ctx *ctx, |
1232 | struct vb2_buffer *src_buf, |
1233 | struct vb2_buffer *dst_buf) |
1234 | { |
1235 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
1236 | void __iomem *reg = jpeg->base_reg; |
1237 | unsigned int slot = ctx->slot; |
1238 | struct mxc_jpeg_desc *desc = jpeg->slot_data.desc; |
1239 | struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc; |
1240 | dma_addr_t desc_handle = jpeg->slot_data.desc_handle; |
1241 | dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle; |
1242 | void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr; |
1243 | struct mxc_jpeg_q_data *q_data; |
1244 | enum mxc_jpeg_image_format img_fmt; |
1245 | int w, h; |
1246 | |
1247 | q_data = mxc_jpeg_get_q_data(ctx, type: src_buf->vb2_queue->type); |
1248 | |
1249 | jpeg->slot_data.cfg_stream_size = |
1250 | mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr, |
1251 | fourcc: q_data->fmt->fourcc, |
1252 | w: q_data->crop.width, |
1253 | h: q_data->crop.height); |
1254 | |
1255 | /* chain the config descriptor with the encoding descriptor */ |
1256 | cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN; |
1257 | |
1258 | cfg_desc->buf_base0 = jpeg->slot_data.cfg_stream_handle; |
1259 | cfg_desc->buf_base1 = 0; |
1260 | cfg_desc->line_pitch = 0; |
1261 | cfg_desc->stm_bufbase = 0; /* no output expected */ |
1262 | cfg_desc->stm_bufsize = 0x0; |
1263 | cfg_desc->imgsize = 0; |
1264 | cfg_desc->stm_ctrl = STM_CTRL_CONFIG_MOD(1); |
1265 | cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1); |
1266 | |
1267 | desc->next_descpt_ptr = 0; /* end of chain */ |
1268 | |
1269 | /* use adjusted resolution for CAST IP job */ |
1270 | w = q_data->crop.width; |
1271 | h = q_data->crop.height; |
1272 | v4l_bound_align_image(width: &w, wmin: w, MXC_JPEG_MAX_WIDTH, walign: q_data->fmt->h_align, |
1273 | height: &h, hmin: h, MXC_JPEG_MAX_HEIGHT, halign: q_data->fmt->v_align, salign: 0); |
1274 | mxc_jpeg_set_res(desc, w, h); |
1275 | mxc_jpeg_set_line_pitch(desc, line_pitch: q_data->bytesperline[0]); |
1276 | mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(dst_buf, 0), 1024)); |
1277 | img_fmt = mxc_jpeg_fourcc_to_imgfmt(fourcc: q_data->fmt->fourcc); |
1278 | if (img_fmt == MXC_JPEG_INVALID) |
1279 | dev_err(jpeg->dev, "No valid image format detected\n" ); |
1280 | desc->stm_ctrl = STM_CTRL_CONFIG_MOD(0) | |
1281 | STM_CTRL_IMAGE_FORMAT(img_fmt); |
1282 | desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1); |
1283 | if (mxc_jpeg_is_extended_sequential(fmt: q_data->fmt)) |
1284 | desc->stm_ctrl |= STM_CTRL_PIXEL_PRECISION; |
1285 | else |
1286 | desc->stm_ctrl &= ~STM_CTRL_PIXEL_PRECISION; |
1287 | mxc_jpeg_addrs(desc, raw_buf: src_buf, jpeg_buf: dst_buf, offset: 0); |
1288 | dev_dbg(jpeg->dev, "cfg_desc:\n" ); |
1289 | print_descriptor_info(dev: jpeg->dev, desc: cfg_desc); |
1290 | dev_dbg(jpeg->dev, "enc desc:\n" ); |
1291 | print_descriptor_info(dev: jpeg->dev, desc); |
1292 | print_wrapper_info(dev: jpeg->dev, reg); |
1293 | print_cast_status(dev: jpeg->dev, reg, mode: MXC_JPEG_ENCODE); |
1294 | |
1295 | /* validate the configuration descriptor */ |
1296 | mxc_jpeg_set_desc(desc: cfg_desc_handle, reg, slot); |
1297 | } |
1298 | |
1299 | static const struct mxc_jpeg_fmt *mxc_jpeg_get_sibling_format(const struct mxc_jpeg_fmt *fmt) |
1300 | { |
1301 | int i; |
1302 | |
1303 | for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++) { |
1304 | if (mxc_formats[i].subsampling == fmt->subsampling && |
1305 | mxc_formats[i].nc == fmt->nc && |
1306 | mxc_formats[i].precision == fmt->precision && |
1307 | mxc_formats[i].is_rgb == fmt->is_rgb && |
1308 | mxc_formats[i].fourcc != fmt->fourcc) |
1309 | return &mxc_formats[i]; |
1310 | } |
1311 | |
1312 | return NULL; |
1313 | } |
1314 | |
1315 | static bool mxc_jpeg_compare_format(const struct mxc_jpeg_fmt *fmt1, |
1316 | const struct mxc_jpeg_fmt *fmt2) |
1317 | { |
1318 | if (fmt1 == fmt2) |
1319 | return true; |
1320 | if (mxc_jpeg_get_sibling_format(fmt: fmt1) == fmt2) |
1321 | return true; |
1322 | return false; |
1323 | } |
1324 | |
1325 | static void mxc_jpeg_set_last_buffer(struct mxc_jpeg_ctx *ctx) |
1326 | { |
1327 | struct vb2_v4l2_buffer *next_dst_buf; |
1328 | |
1329 | next_dst_buf = v4l2_m2m_dst_buf_remove(m2m_ctx: ctx->fh.m2m_ctx); |
1330 | if (!next_dst_buf) { |
1331 | ctx->fh.m2m_ctx->is_draining = true; |
1332 | ctx->fh.m2m_ctx->next_buf_last = true; |
1333 | return; |
1334 | } |
1335 | |
1336 | v4l2_m2m_last_buffer_done(m2m_ctx: ctx->fh.m2m_ctx, vbuf: next_dst_buf); |
1337 | } |
1338 | |
1339 | static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx, |
1340 | struct mxc_jpeg_src_buf *jpeg_src_buf) |
1341 | { |
1342 | struct device *dev = ctx->mxc_jpeg->dev; |
1343 | struct mxc_jpeg_q_data *q_data_cap; |
1344 | |
1345 | if (!jpeg_src_buf->fmt) |
1346 | return false; |
1347 | |
1348 | q_data_cap = mxc_jpeg_get_q_data(ctx, type: V4L2_BUF_TYPE_VIDEO_CAPTURE); |
1349 | if (mxc_jpeg_compare_format(fmt1: q_data_cap->fmt, fmt2: jpeg_src_buf->fmt)) |
1350 | jpeg_src_buf->fmt = q_data_cap->fmt; |
1351 | if (ctx->need_initial_source_change_evt || |
1352 | q_data_cap->fmt != jpeg_src_buf->fmt || |
1353 | q_data_cap->w != jpeg_src_buf->w || |
1354 | q_data_cap->h != jpeg_src_buf->h) { |
1355 | dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n" , |
1356 | q_data_cap->w, q_data_cap->h, |
1357 | jpeg_src_buf->w, jpeg_src_buf->h, |
1358 | (jpeg_src_buf->fmt->fourcc & 0xff), |
1359 | (jpeg_src_buf->fmt->fourcc >> 8) & 0xff, |
1360 | (jpeg_src_buf->fmt->fourcc >> 16) & 0xff, |
1361 | (jpeg_src_buf->fmt->fourcc >> 24) & 0xff); |
1362 | |
1363 | /* |
1364 | * set-up the capture queue with the pixelformat and resolution |
1365 | * detected from the jpeg output stream |
1366 | */ |
1367 | q_data_cap->w = jpeg_src_buf->w; |
1368 | q_data_cap->h = jpeg_src_buf->h; |
1369 | q_data_cap->fmt = jpeg_src_buf->fmt; |
1370 | q_data_cap->w_adjusted = q_data_cap->w; |
1371 | q_data_cap->h_adjusted = q_data_cap->h; |
1372 | q_data_cap->crop.left = 0; |
1373 | q_data_cap->crop.top = 0; |
1374 | q_data_cap->crop.width = jpeg_src_buf->w; |
1375 | q_data_cap->crop.height = jpeg_src_buf->h; |
1376 | q_data_cap->bytesperline[0] = 0; |
1377 | q_data_cap->bytesperline[1] = 0; |
1378 | |
1379 | /* |
1380 | * align up the resolution for CAST IP, |
1381 | * but leave the buffer resolution unchanged |
1382 | */ |
1383 | v4l_bound_align_image(width: &q_data_cap->w_adjusted, |
1384 | wmin: q_data_cap->w_adjusted, /* adjust up */ |
1385 | MXC_JPEG_MAX_WIDTH, |
1386 | walign: q_data_cap->fmt->h_align, |
1387 | height: &q_data_cap->h_adjusted, |
1388 | hmin: q_data_cap->h_adjusted, /* adjust up */ |
1389 | MXC_JPEG_MAX_HEIGHT, |
1390 | halign: q_data_cap->fmt->v_align, |
1391 | salign: 0); |
1392 | |
1393 | /* setup bytesperline/sizeimage for capture queue */ |
1394 | mxc_jpeg_bytesperline(q: q_data_cap, precision: jpeg_src_buf->fmt->precision); |
1395 | mxc_jpeg_sizeimage(q: q_data_cap); |
1396 | notify_src_chg(ctx); |
1397 | ctx->source_change = 1; |
1398 | ctx->need_initial_source_change_evt = false; |
1399 | if (vb2_is_streaming(q: v4l2_m2m_get_dst_vq(m2m_ctx: ctx->fh.m2m_ctx))) |
1400 | mxc_jpeg_set_last_buffer(ctx); |
1401 | } |
1402 | |
1403 | return ctx->source_change ? true : false; |
1404 | } |
1405 | |
1406 | static int mxc_jpeg_job_ready(void *priv) |
1407 | { |
1408 | struct mxc_jpeg_ctx *ctx = priv; |
1409 | |
1410 | return ctx->source_change ? 0 : 1; |
1411 | } |
1412 | |
1413 | static void mxc_jpeg_device_run_timeout(struct work_struct *work) |
1414 | { |
1415 | struct delayed_work *dwork = to_delayed_work(work); |
1416 | struct mxc_jpeg_ctx *ctx = container_of(dwork, struct mxc_jpeg_ctx, task_timer); |
1417 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
1418 | unsigned long flags; |
1419 | |
1420 | spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags); |
1421 | if (ctx->mxc_jpeg->slot_data.used) { |
1422 | dev_warn(jpeg->dev, "%s timeout, cancel it\n" , |
1423 | ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? "decode" : "encode" ); |
1424 | mxc_jpeg_job_finish(ctx, state: VB2_BUF_STATE_ERROR, reset: true); |
1425 | v4l2_m2m_job_finish(m2m_dev: ctx->mxc_jpeg->m2m_dev, m2m_ctx: ctx->fh.m2m_ctx); |
1426 | } |
1427 | spin_unlock_irqrestore(lock: &ctx->mxc_jpeg->hw_lock, flags); |
1428 | } |
1429 | |
1430 | static void mxc_jpeg_device_run(void *priv) |
1431 | { |
1432 | struct mxc_jpeg_ctx *ctx = priv; |
1433 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
1434 | void __iomem *reg = jpeg->base_reg; |
1435 | struct device *dev = jpeg->dev; |
1436 | struct vb2_v4l2_buffer *src_buf, *dst_buf; |
1437 | unsigned long flags; |
1438 | struct mxc_jpeg_q_data *q_data_cap, *q_data_out; |
1439 | struct mxc_jpeg_src_buf *jpeg_src_buf; |
1440 | |
1441 | spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags); |
1442 | src_buf = v4l2_m2m_next_src_buf(m2m_ctx: ctx->fh.m2m_ctx); |
1443 | dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx: ctx->fh.m2m_ctx); |
1444 | if (!src_buf || !dst_buf) { |
1445 | dev_err(dev, "Null src or dst buf\n" ); |
1446 | goto end; |
1447 | } |
1448 | |
1449 | q_data_cap = mxc_jpeg_get_q_data(ctx, type: V4L2_BUF_TYPE_VIDEO_CAPTURE); |
1450 | if (!q_data_cap) |
1451 | goto end; |
1452 | q_data_out = mxc_jpeg_get_q_data(ctx, type: V4L2_BUF_TYPE_VIDEO_OUTPUT); |
1453 | if (!q_data_out) |
1454 | goto end; |
1455 | src_buf->sequence = q_data_out->sequence++; |
1456 | dst_buf->sequence = q_data_cap->sequence++; |
1457 | |
1458 | v4l2_m2m_buf_copy_metadata(out_vb: src_buf, cap_vb: dst_buf, copy_frame_flags: true); |
1459 | |
1460 | jpeg_src_buf = vb2_to_mxc_buf(vb: &src_buf->vb2_buf); |
1461 | if (q_data_cap->fmt->mem_planes != dst_buf->vb2_buf.num_planes) { |
1462 | dev_err(dev, "Capture format %s has %d planes, but capture buffer has %d planes\n" , |
1463 | q_data_cap->fmt->name, q_data_cap->fmt->mem_planes, |
1464 | dst_buf->vb2_buf.num_planes); |
1465 | jpeg_src_buf->jpeg_parse_error = true; |
1466 | } |
1467 | if (jpeg_src_buf->jpeg_parse_error) { |
1468 | mxc_jpeg_check_and_set_last_buffer(ctx, src_buf, dst_buf); |
1469 | v4l2_m2m_src_buf_remove(m2m_ctx: ctx->fh.m2m_ctx); |
1470 | v4l2_m2m_dst_buf_remove(m2m_ctx: ctx->fh.m2m_ctx); |
1471 | v4l2_m2m_buf_done(buf: src_buf, state: VB2_BUF_STATE_ERROR); |
1472 | v4l2_m2m_buf_done(buf: dst_buf, state: VB2_BUF_STATE_ERROR); |
1473 | spin_unlock_irqrestore(lock: &ctx->mxc_jpeg->hw_lock, flags); |
1474 | v4l2_m2m_job_finish(m2m_dev: jpeg->m2m_dev, m2m_ctx: ctx->fh.m2m_ctx); |
1475 | |
1476 | return; |
1477 | } |
1478 | if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) { |
1479 | if (ctx->source_change || mxc_jpeg_source_change(ctx, jpeg_src_buf)) { |
1480 | spin_unlock_irqrestore(lock: &ctx->mxc_jpeg->hw_lock, flags); |
1481 | v4l2_m2m_job_finish(m2m_dev: jpeg->m2m_dev, m2m_ctx: ctx->fh.m2m_ctx); |
1482 | return; |
1483 | } |
1484 | } |
1485 | |
1486 | mxc_jpeg_enable(reg); |
1487 | mxc_jpeg_set_l_endian(reg, le: 1); |
1488 | |
1489 | ctx->slot = mxc_get_free_slot(slot_data: &jpeg->slot_data); |
1490 | if (ctx->slot < 0) { |
1491 | dev_err(dev, "No more free slots\n" ); |
1492 | goto end; |
1493 | } |
1494 | if (!mxc_jpeg_alloc_slot_data(jpeg)) { |
1495 | dev_err(dev, "Cannot allocate slot data\n" ); |
1496 | goto end; |
1497 | } |
1498 | |
1499 | mxc_jpeg_enable_slot(reg, slot: ctx->slot); |
1500 | mxc_jpeg_enable_irq(reg, slot: ctx->slot); |
1501 | |
1502 | if (jpeg->mode == MXC_JPEG_ENCODE) { |
1503 | dev_dbg(dev, "Encoding on slot %d\n" , ctx->slot); |
1504 | ctx->enc_state = MXC_JPEG_ENC_CONF; |
1505 | mxc_jpeg_config_enc_desc(out_buf: &dst_buf->vb2_buf, ctx, |
1506 | src_buf: &src_buf->vb2_buf, dst_buf: &dst_buf->vb2_buf); |
1507 | /* start config phase */ |
1508 | mxc_jpeg_enc_mode_conf(dev, reg, |
1509 | extseq: mxc_jpeg_is_extended_sequential(fmt: q_data_out->fmt)); |
1510 | } else { |
1511 | dev_dbg(dev, "Decoding on slot %d\n" , ctx->slot); |
1512 | print_mxc_buf(jpeg, buf: &src_buf->vb2_buf, len: 0); |
1513 | mxc_jpeg_config_dec_desc(out_buf: &dst_buf->vb2_buf, ctx, |
1514 | src_buf: &src_buf->vb2_buf, dst_buf: &dst_buf->vb2_buf); |
1515 | mxc_jpeg_dec_mode_go(dev, reg); |
1516 | } |
1517 | schedule_delayed_work(dwork: &ctx->task_timer, delay: msecs_to_jiffies(m: hw_timeout)); |
1518 | end: |
1519 | spin_unlock_irqrestore(lock: &ctx->mxc_jpeg->hw_lock, flags); |
1520 | } |
1521 | |
1522 | static int mxc_jpeg_decoder_cmd(struct file *file, void *priv, |
1523 | struct v4l2_decoder_cmd *cmd) |
1524 | { |
1525 | struct v4l2_fh *fh = file->private_data; |
1526 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); |
1527 | unsigned long flags; |
1528 | int ret; |
1529 | |
1530 | ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc: cmd); |
1531 | if (ret < 0) |
1532 | return ret; |
1533 | |
1534 | if (!vb2_is_streaming(q: v4l2_m2m_get_src_vq(m2m_ctx: fh->m2m_ctx))) |
1535 | return 0; |
1536 | |
1537 | spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags); |
1538 | ret = v4l2_m2m_ioctl_decoder_cmd(file, fh: priv, dc: cmd); |
1539 | spin_unlock_irqrestore(lock: &ctx->mxc_jpeg->hw_lock, flags); |
1540 | if (ret < 0) |
1541 | return ret; |
1542 | |
1543 | if (cmd->cmd == V4L2_DEC_CMD_STOP && |
1544 | v4l2_m2m_has_stopped(m2m_ctx: fh->m2m_ctx)) { |
1545 | notify_eos(ctx); |
1546 | ctx->header_parsed = false; |
1547 | } |
1548 | |
1549 | if (cmd->cmd == V4L2_DEC_CMD_START && |
1550 | v4l2_m2m_has_stopped(m2m_ctx: fh->m2m_ctx)) |
1551 | vb2_clear_last_buffer_dequeued(q: &fh->m2m_ctx->cap_q_ctx.q); |
1552 | return 0; |
1553 | } |
1554 | |
1555 | static int mxc_jpeg_encoder_cmd(struct file *file, void *priv, |
1556 | struct v4l2_encoder_cmd *cmd) |
1557 | { |
1558 | struct v4l2_fh *fh = file->private_data; |
1559 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); |
1560 | unsigned long flags; |
1561 | int ret; |
1562 | |
1563 | ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec: cmd); |
1564 | if (ret < 0) |
1565 | return ret; |
1566 | |
1567 | if (!vb2_is_streaming(q: v4l2_m2m_get_src_vq(m2m_ctx: fh->m2m_ctx)) || |
1568 | !vb2_is_streaming(q: v4l2_m2m_get_dst_vq(m2m_ctx: fh->m2m_ctx))) |
1569 | return 0; |
1570 | |
1571 | spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags); |
1572 | ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, ec: cmd); |
1573 | spin_unlock_irqrestore(lock: &ctx->mxc_jpeg->hw_lock, flags); |
1574 | if (ret < 0) |
1575 | return 0; |
1576 | |
1577 | if (cmd->cmd == V4L2_ENC_CMD_STOP && |
1578 | v4l2_m2m_has_stopped(m2m_ctx: fh->m2m_ctx)) |
1579 | notify_eos(ctx); |
1580 | |
1581 | if (cmd->cmd == V4L2_ENC_CMD_START && |
1582 | v4l2_m2m_has_stopped(m2m_ctx: fh->m2m_ctx)) |
1583 | vb2_clear_last_buffer_dequeued(q: &fh->m2m_ctx->cap_q_ctx.q); |
1584 | |
1585 | return 0; |
1586 | } |
1587 | |
1588 | static int mxc_jpeg_queue_setup(struct vb2_queue *q, |
1589 | unsigned int *nbuffers, |
1590 | unsigned int *nplanes, |
1591 | unsigned int sizes[], |
1592 | struct device *alloc_ctxs[]) |
1593 | { |
1594 | struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q); |
1595 | struct mxc_jpeg_q_data *q_data = NULL; |
1596 | int i; |
1597 | |
1598 | q_data = mxc_jpeg_get_q_data(ctx, type: q->type); |
1599 | if (!q_data) |
1600 | return -EINVAL; |
1601 | |
1602 | /* Handle CREATE_BUFS situation - *nplanes != 0 */ |
1603 | if (*nplanes) { |
1604 | if (*nplanes != q_data->fmt->mem_planes) |
1605 | return -EINVAL; |
1606 | for (i = 0; i < *nplanes; i++) { |
1607 | if (sizes[i] < mxc_jpeg_get_plane_size(q_data, plane_no: i)) |
1608 | return -EINVAL; |
1609 | } |
1610 | return 0; |
1611 | } |
1612 | |
1613 | /* Handle REQBUFS situation */ |
1614 | *nplanes = q_data->fmt->mem_planes; |
1615 | for (i = 0; i < *nplanes; i++) |
1616 | sizes[i] = mxc_jpeg_get_plane_size(q_data, plane_no: i); |
1617 | |
1618 | if (V4L2_TYPE_IS_OUTPUT(q->type)) |
1619 | ctx->need_initial_source_change_evt = true; |
1620 | |
1621 | return 0; |
1622 | } |
1623 | |
1624 | static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count) |
1625 | { |
1626 | struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q); |
1627 | struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, type: q->type); |
1628 | int ret; |
1629 | |
1630 | v4l2_m2m_update_start_streaming_state(m2m_ctx: ctx->fh.m2m_ctx, q); |
1631 | |
1632 | if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(q->type)) |
1633 | ctx->source_change = 0; |
1634 | dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p" , ctx); |
1635 | q_data->sequence = 0; |
1636 | |
1637 | ret = pm_runtime_resume_and_get(dev: ctx->mxc_jpeg->dev); |
1638 | if (ret < 0) { |
1639 | dev_err(ctx->mxc_jpeg->dev, "Failed to power up jpeg\n" ); |
1640 | return ret; |
1641 | } |
1642 | |
1643 | return 0; |
1644 | } |
1645 | |
1646 | static void mxc_jpeg_stop_streaming(struct vb2_queue *q) |
1647 | { |
1648 | struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q); |
1649 | struct vb2_v4l2_buffer *vbuf; |
1650 | |
1651 | dev_dbg(ctx->mxc_jpeg->dev, "Stop streaming ctx=%p" , ctx); |
1652 | |
1653 | /* Release all active buffers */ |
1654 | for (;;) { |
1655 | if (V4L2_TYPE_IS_OUTPUT(q->type)) |
1656 | vbuf = v4l2_m2m_src_buf_remove(m2m_ctx: ctx->fh.m2m_ctx); |
1657 | else |
1658 | vbuf = v4l2_m2m_dst_buf_remove(m2m_ctx: ctx->fh.m2m_ctx); |
1659 | if (!vbuf) |
1660 | break; |
1661 | v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_ERROR); |
1662 | } |
1663 | |
1664 | v4l2_m2m_update_stop_streaming_state(m2m_ctx: ctx->fh.m2m_ctx, q); |
1665 | /* if V4L2_DEC_CMD_STOP is sent before the source change triggered, |
1666 | * restore the is_draining flag |
1667 | */ |
1668 | if (V4L2_TYPE_IS_CAPTURE(q->type) && ctx->source_change && ctx->fh.m2m_ctx->last_src_buf) |
1669 | ctx->fh.m2m_ctx->is_draining = true; |
1670 | |
1671 | if (V4L2_TYPE_IS_OUTPUT(q->type) && |
1672 | v4l2_m2m_has_stopped(m2m_ctx: ctx->fh.m2m_ctx)) { |
1673 | notify_eos(ctx); |
1674 | ctx->header_parsed = false; |
1675 | } |
1676 | |
1677 | pm_runtime_put_sync(dev: &ctx->mxc_jpeg->pdev->dev); |
1678 | } |
1679 | |
1680 | static int mxc_jpeg_valid_comp_id(struct device *dev, |
1681 | struct mxc_jpeg_sof *sof, |
1682 | struct mxc_jpeg_sos *sos) |
1683 | { |
1684 | int valid = 1; |
1685 | int i; |
1686 | |
1687 | /* |
1688 | * there's a limitation in the IP that the component IDs must be |
1689 | * between 0..4, if they are not, let's patch them |
1690 | */ |
1691 | for (i = 0; i < sof->components_no; i++) |
1692 | if (sof->comp[i].id > MXC_JPEG_MAX_COMPONENTS) { |
1693 | valid = 0; |
1694 | dev_err(dev, "Component %d has invalid ID: %d" , |
1695 | i, sof->comp[i].id); |
1696 | } |
1697 | if (!valid) |
1698 | /* patch all comp IDs if at least one is invalid */ |
1699 | for (i = 0; i < sof->components_no; i++) { |
1700 | dev_warn(dev, "Component %d ID patched to: %d" , |
1701 | i, i + 1); |
1702 | sof->comp[i].id = i + 1; |
1703 | sos->comp[i].id = i + 1; |
1704 | } |
1705 | |
1706 | return valid; |
1707 | } |
1708 | |
1709 | static bool mxc_jpeg_match_image_format(const struct mxc_jpeg_fmt *fmt, |
1710 | const struct v4l2_jpeg_header *) |
1711 | { |
1712 | if (fmt->subsampling != header->frame.subsampling || |
1713 | fmt->nc != header->frame.num_components || |
1714 | fmt->precision != header->frame.precision) |
1715 | return false; |
1716 | |
1717 | /* |
1718 | * If the transform flag from APP14 marker is 0, images that are |
1719 | * encoded with 3 components have RGB colorspace, see Recommendation |
1720 | * ITU-T T.872 chapter 6.5.3 APP14 marker segment for colour encoding |
1721 | */ |
1722 | if (header->frame.subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_444) { |
1723 | u8 is_rgb = header->app14_tf == V4L2_JPEG_APP14_TF_CMYK_RGB ? 1 : 0; |
1724 | |
1725 | if (is_rgb != fmt->is_rgb) |
1726 | return false; |
1727 | } |
1728 | return true; |
1729 | } |
1730 | |
1731 | static u32 mxc_jpeg_get_image_format(struct device *dev, |
1732 | const struct v4l2_jpeg_header *) |
1733 | { |
1734 | int i; |
1735 | u32 fourcc = 0; |
1736 | |
1737 | for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++) { |
1738 | if (mxc_jpeg_match_image_format(fmt: &mxc_formats[i], header)) { |
1739 | fourcc = mxc_formats[i].fourcc; |
1740 | break; |
1741 | } |
1742 | } |
1743 | if (fourcc == 0) { |
1744 | dev_err(dev, |
1745 | "Could not identify image format nc=%d, subsampling=%d, precision=%d\n" , |
1746 | header->frame.num_components, |
1747 | header->frame.subsampling, |
1748 | header->frame.precision); |
1749 | return fourcc; |
1750 | } |
1751 | |
1752 | return fourcc; |
1753 | } |
1754 | |
1755 | static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision) |
1756 | { |
1757 | u32 bytesperline[2]; |
1758 | |
1759 | bytesperline[0] = q->bytesperline[0]; |
1760 | bytesperline[1] = q->bytesperline[0]; /*imx-jpeg only support the same line pitch*/ |
1761 | v4l_bound_align_image(width: &bytesperline[0], wmin: 0, MXC_JPEG_MAX_LINE, walign: 2, |
1762 | height: &bytesperline[1], hmin: 0, MXC_JPEG_MAX_LINE, halign: 2, |
1763 | salign: 0); |
1764 | |
1765 | /* Bytes distance between the leftmost pixels in two adjacent lines */ |
1766 | if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) { |
1767 | /* bytesperline unused for compressed formats */ |
1768 | q->bytesperline[0] = 0; |
1769 | q->bytesperline[1] = 0; |
1770 | } else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420) { |
1771 | /* When the image format is planar the bytesperline value |
1772 | * applies to the first plane and is divided by the same factor |
1773 | * as the width field for the other planes |
1774 | */ |
1775 | q->bytesperline[0] = q->w_adjusted * DIV_ROUND_UP(precision, 8); |
1776 | q->bytesperline[1] = q->bytesperline[0]; |
1777 | } else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422) { |
1778 | q->bytesperline[0] = q->w_adjusted * DIV_ROUND_UP(precision, 8) * 2; |
1779 | q->bytesperline[1] = 0; |
1780 | } else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_444) { |
1781 | q->bytesperline[0] = q->w_adjusted * DIV_ROUND_UP(precision, 8) * q->fmt->nc; |
1782 | q->bytesperline[1] = 0; |
1783 | } else { |
1784 | /* grayscale */ |
1785 | q->bytesperline[0] = q->w_adjusted * DIV_ROUND_UP(precision, 8); |
1786 | q->bytesperline[1] = 0; |
1787 | } |
1788 | |
1789 | if (q->fmt->fourcc != V4L2_PIX_FMT_JPEG) { |
1790 | q->bytesperline[0] = max(q->bytesperline[0], bytesperline[0]); |
1791 | if (q->fmt->mem_planes > 1) |
1792 | q->bytesperline[1] = max(q->bytesperline[1], bytesperline[1]); |
1793 | } |
1794 | } |
1795 | |
1796 | static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q) |
1797 | { |
1798 | if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) { |
1799 | /* if no sizeimage from user, assume worst jpeg compression */ |
1800 | if (!q->sizeimage[0]) |
1801 | q->sizeimage[0] = 6 * q->w * q->h; |
1802 | q->sizeimage[1] = 0; |
1803 | |
1804 | if (q->sizeimage[0] > MXC_JPEG_MAX_SIZEIMAGE) |
1805 | q->sizeimage[0] = MXC_JPEG_MAX_SIZEIMAGE; |
1806 | |
1807 | /* jpeg stream size must be multiple of 1K */ |
1808 | q->sizeimage[0] = ALIGN(q->sizeimage[0], 1024); |
1809 | } else { |
1810 | q->sizeimage[0] = q->bytesperline[0] * q->h_adjusted; |
1811 | q->sizeimage[1] = 0; |
1812 | if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420) |
1813 | q->sizeimage[1] = q->sizeimage[0] / 2; |
1814 | } |
1815 | } |
1816 | |
1817 | static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb) |
1818 | { |
1819 | struct device *dev = ctx->mxc_jpeg->dev; |
1820 | struct mxc_jpeg_q_data *q_data_out; |
1821 | struct mxc_jpeg_q_data *q_data_cap; |
1822 | u32 fourcc; |
1823 | struct v4l2_jpeg_header ; |
1824 | struct mxc_jpeg_sof *psof = NULL; |
1825 | struct mxc_jpeg_sos *psos = NULL; |
1826 | struct mxc_jpeg_src_buf *jpeg_src_buf = vb2_to_mxc_buf(vb); |
1827 | u8 *src_addr = (u8 *)vb2_plane_vaddr(vb, plane_no: 0); |
1828 | u32 size = vb2_get_plane_payload(vb, plane_no: 0); |
1829 | int ret; |
1830 | |
1831 | memset(&header, 0, sizeof(header)); |
1832 | ret = v4l2_jpeg_parse_header(buf: (void *)src_addr, len: size, out: &header); |
1833 | if (ret < 0) { |
1834 | dev_err(dev, "Error parsing JPEG stream markers\n" ); |
1835 | return ret; |
1836 | } |
1837 | |
1838 | /* if DHT marker present, no need to inject default one */ |
1839 | jpeg_src_buf->dht_needed = (header.num_dht == 0); |
1840 | |
1841 | q_data_out = mxc_jpeg_get_q_data(ctx, |
1842 | type: V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); |
1843 | if (q_data_out->w == 0 && q_data_out->h == 0) { |
1844 | dev_warn(dev, "Invalid user resolution 0x0" ); |
1845 | dev_warn(dev, "Keeping resolution from JPEG: %dx%d" , |
1846 | header.frame.width, header.frame.height); |
1847 | } else if (header.frame.width != q_data_out->w || |
1848 | header.frame.height != q_data_out->h) { |
1849 | dev_err(dev, |
1850 | "Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)" , |
1851 | header.frame.width, header.frame.height, |
1852 | q_data_out->w, q_data_out->h); |
1853 | } |
1854 | q_data_out->w = header.frame.width; |
1855 | q_data_out->h = header.frame.height; |
1856 | if (header.frame.width > MXC_JPEG_MAX_WIDTH || |
1857 | header.frame.height > MXC_JPEG_MAX_HEIGHT) { |
1858 | dev_err(dev, "JPEG width or height should be <= 8192: %dx%d\n" , |
1859 | header.frame.width, header.frame.height); |
1860 | return -EINVAL; |
1861 | } |
1862 | if (header.frame.width < MXC_JPEG_MIN_WIDTH || |
1863 | header.frame.height < MXC_JPEG_MIN_HEIGHT) { |
1864 | dev_err(dev, "JPEG width or height should be > 64: %dx%d\n" , |
1865 | header.frame.width, header.frame.height); |
1866 | return -EINVAL; |
1867 | } |
1868 | if (header.frame.num_components > V4L2_JPEG_MAX_COMPONENTS) { |
1869 | dev_err(dev, "JPEG number of components should be <=%d" , |
1870 | V4L2_JPEG_MAX_COMPONENTS); |
1871 | return -EINVAL; |
1872 | } |
1873 | /* check and, if necessary, patch component IDs*/ |
1874 | psof = (struct mxc_jpeg_sof *)header.sof.start; |
1875 | psos = (struct mxc_jpeg_sos *)header.sos.start; |
1876 | if (!mxc_jpeg_valid_comp_id(dev, sof: psof, sos: psos)) |
1877 | dev_warn(dev, "JPEG component ids should be 0-3 or 1-4" ); |
1878 | |
1879 | q_data_cap = mxc_jpeg_get_q_data(ctx, type: V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); |
1880 | if (q_data_cap->fmt && mxc_jpeg_match_image_format(fmt: q_data_cap->fmt, header: &header)) |
1881 | fourcc = q_data_cap->fmt->fourcc; |
1882 | else |
1883 | fourcc = mxc_jpeg_get_image_format(dev, header: &header); |
1884 | if (fourcc == 0) |
1885 | return -EINVAL; |
1886 | |
1887 | jpeg_src_buf->fmt = mxc_jpeg_find_format(pixelformat: fourcc); |
1888 | jpeg_src_buf->w = header.frame.width; |
1889 | jpeg_src_buf->h = header.frame.height; |
1890 | ctx->header_parsed = true; |
1891 | |
1892 | if (!v4l2_m2m_num_src_bufs_ready(m2m_ctx: ctx->fh.m2m_ctx)) |
1893 | mxc_jpeg_source_change(ctx, jpeg_src_buf); |
1894 | |
1895 | return 0; |
1896 | } |
1897 | |
1898 | static void mxc_jpeg_buf_queue(struct vb2_buffer *vb) |
1899 | { |
1900 | int ret; |
1901 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
1902 | struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q: vb->vb2_queue); |
1903 | struct mxc_jpeg_src_buf *jpeg_src_buf; |
1904 | |
1905 | if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) && |
1906 | vb2_is_streaming(q: vb->vb2_queue) && |
1907 | v4l2_m2m_dst_buf_is_last(m2m_ctx: ctx->fh.m2m_ctx)) { |
1908 | struct mxc_jpeg_q_data *q_data; |
1909 | |
1910 | q_data = mxc_jpeg_get_q_data(ctx, type: vb->vb2_queue->type); |
1911 | vbuf->field = V4L2_FIELD_NONE; |
1912 | vbuf->sequence = q_data->sequence++; |
1913 | v4l2_m2m_last_buffer_done(m2m_ctx: ctx->fh.m2m_ctx, vbuf); |
1914 | notify_eos(ctx); |
1915 | ctx->header_parsed = false; |
1916 | return; |
1917 | } |
1918 | |
1919 | if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
1920 | goto end; |
1921 | |
1922 | /* for V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE */ |
1923 | if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE) |
1924 | goto end; |
1925 | |
1926 | jpeg_src_buf = vb2_to_mxc_buf(vb); |
1927 | jpeg_src_buf->jpeg_parse_error = false; |
1928 | ret = mxc_jpeg_parse(ctx, vb); |
1929 | if (ret) |
1930 | jpeg_src_buf->jpeg_parse_error = true; |
1931 | |
1932 | end: |
1933 | v4l2_m2m_buf_queue(m2m_ctx: ctx->fh.m2m_ctx, vbuf); |
1934 | } |
1935 | |
1936 | static int mxc_jpeg_buf_out_validate(struct vb2_buffer *vb) |
1937 | { |
1938 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
1939 | |
1940 | vbuf->field = V4L2_FIELD_NONE; |
1941 | |
1942 | return 0; |
1943 | } |
1944 | |
1945 | static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb) |
1946 | { |
1947 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
1948 | struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q: vb->vb2_queue); |
1949 | struct mxc_jpeg_q_data *q_data = NULL; |
1950 | struct device *dev = ctx->mxc_jpeg->dev; |
1951 | unsigned long sizeimage; |
1952 | int i; |
1953 | |
1954 | vbuf->field = V4L2_FIELD_NONE; |
1955 | |
1956 | q_data = mxc_jpeg_get_q_data(ctx, type: vb->vb2_queue->type); |
1957 | if (!q_data) |
1958 | return -EINVAL; |
1959 | for (i = 0; i < q_data->fmt->mem_planes; i++) { |
1960 | sizeimage = mxc_jpeg_get_plane_size(q_data, plane_no: i); |
1961 | if (!ctx->source_change && vb2_plane_size(vb, plane_no: i) < sizeimage) { |
1962 | dev_err(dev, "plane %d too small (%lu < %lu)" , |
1963 | i, vb2_plane_size(vb, i), sizeimage); |
1964 | return -EINVAL; |
1965 | } |
1966 | } |
1967 | if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { |
1968 | vb2_set_plane_payload(vb, plane_no: 0, size: 0); |
1969 | vb2_set_plane_payload(vb, plane_no: 1, size: 0); |
1970 | } |
1971 | return 0; |
1972 | } |
1973 | |
1974 | static const struct vb2_ops mxc_jpeg_qops = { |
1975 | .queue_setup = mxc_jpeg_queue_setup, |
1976 | .wait_prepare = vb2_ops_wait_prepare, |
1977 | .wait_finish = vb2_ops_wait_finish, |
1978 | .buf_out_validate = mxc_jpeg_buf_out_validate, |
1979 | .buf_prepare = mxc_jpeg_buf_prepare, |
1980 | .start_streaming = mxc_jpeg_start_streaming, |
1981 | .stop_streaming = mxc_jpeg_stop_streaming, |
1982 | .buf_queue = mxc_jpeg_buf_queue, |
1983 | }; |
1984 | |
1985 | static int mxc_jpeg_queue_init(void *priv, struct vb2_queue *src_vq, |
1986 | struct vb2_queue *dst_vq) |
1987 | { |
1988 | struct mxc_jpeg_ctx *ctx = priv; |
1989 | int ret; |
1990 | |
1991 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1992 | src_vq->io_modes = VB2_MMAP | VB2_DMABUF; |
1993 | src_vq->drv_priv = ctx; |
1994 | src_vq->buf_struct_size = sizeof(struct mxc_jpeg_src_buf); |
1995 | src_vq->ops = &mxc_jpeg_qops; |
1996 | src_vq->mem_ops = &vb2_dma_contig_memops; |
1997 | src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; |
1998 | src_vq->lock = &ctx->mxc_jpeg->lock; |
1999 | src_vq->dev = ctx->mxc_jpeg->dev; |
2000 | |
2001 | ret = vb2_queue_init(q: src_vq); |
2002 | if (ret) |
2003 | return ret; |
2004 | |
2005 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
2006 | dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; |
2007 | dst_vq->drv_priv = ctx; |
2008 | dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); |
2009 | dst_vq->ops = &mxc_jpeg_qops; |
2010 | dst_vq->mem_ops = &vb2_dma_contig_memops; |
2011 | dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; |
2012 | dst_vq->lock = &ctx->mxc_jpeg->lock; |
2013 | dst_vq->dev = ctx->mxc_jpeg->dev; |
2014 | |
2015 | ret = vb2_queue_init(q: dst_vq); |
2016 | return ret; |
2017 | } |
2018 | |
2019 | static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx) |
2020 | { |
2021 | struct mxc_jpeg_q_data *out_q = &ctx->out_q; |
2022 | struct mxc_jpeg_q_data *cap_q = &ctx->cap_q; |
2023 | struct mxc_jpeg_q_data *q[2] = {out_q, cap_q}; |
2024 | int i; |
2025 | |
2026 | if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) { |
2027 | out_q->fmt = mxc_jpeg_find_format(MXC_JPEG_DEFAULT_PFMT); |
2028 | cap_q->fmt = mxc_jpeg_find_format(V4L2_PIX_FMT_JPEG); |
2029 | } else { |
2030 | out_q->fmt = mxc_jpeg_find_format(V4L2_PIX_FMT_JPEG); |
2031 | cap_q->fmt = mxc_jpeg_find_format(MXC_JPEG_DEFAULT_PFMT); |
2032 | } |
2033 | |
2034 | for (i = 0; i < 2; i++) { |
2035 | q[i]->w = MXC_JPEG_DEFAULT_WIDTH; |
2036 | q[i]->h = MXC_JPEG_DEFAULT_HEIGHT; |
2037 | q[i]->w_adjusted = MXC_JPEG_DEFAULT_WIDTH; |
2038 | q[i]->h_adjusted = MXC_JPEG_DEFAULT_HEIGHT; |
2039 | q[i]->crop.left = 0; |
2040 | q[i]->crop.top = 0; |
2041 | q[i]->crop.width = MXC_JPEG_DEFAULT_WIDTH; |
2042 | q[i]->crop.height = MXC_JPEG_DEFAULT_HEIGHT; |
2043 | mxc_jpeg_bytesperline(q: q[i], precision: q[i]->fmt->precision); |
2044 | mxc_jpeg_sizeimage(q: q[i]); |
2045 | } |
2046 | } |
2047 | |
2048 | static int mxc_jpeg_s_ctrl(struct v4l2_ctrl *ctrl) |
2049 | { |
2050 | struct mxc_jpeg_ctx *ctx = |
2051 | container_of(ctrl->handler, struct mxc_jpeg_ctx, ctrl_handler); |
2052 | |
2053 | switch (ctrl->id) { |
2054 | case V4L2_CID_JPEG_COMPRESSION_QUALITY: |
2055 | ctx->jpeg_quality = ctrl->val; |
2056 | break; |
2057 | default: |
2058 | dev_err(ctx->mxc_jpeg->dev, "Invalid control, id = %d, val = %d\n" , |
2059 | ctrl->id, ctrl->val); |
2060 | return -EINVAL; |
2061 | } |
2062 | |
2063 | return 0; |
2064 | } |
2065 | |
2066 | static const struct v4l2_ctrl_ops mxc_jpeg_ctrl_ops = { |
2067 | .s_ctrl = mxc_jpeg_s_ctrl, |
2068 | }; |
2069 | |
2070 | static void mxc_jpeg_encode_ctrls(struct mxc_jpeg_ctx *ctx) |
2071 | { |
2072 | v4l2_ctrl_new_std(hdl: &ctx->ctrl_handler, ops: &mxc_jpeg_ctrl_ops, |
2073 | V4L2_CID_JPEG_COMPRESSION_QUALITY, min: 1, max: 100, step: 1, def: 75); |
2074 | } |
2075 | |
2076 | static int mxc_jpeg_ctrls_setup(struct mxc_jpeg_ctx *ctx) |
2077 | { |
2078 | int err; |
2079 | |
2080 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 2); |
2081 | |
2082 | if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) |
2083 | mxc_jpeg_encode_ctrls(ctx); |
2084 | |
2085 | if (ctx->ctrl_handler.error) { |
2086 | err = ctx->ctrl_handler.error; |
2087 | |
2088 | v4l2_ctrl_handler_free(hdl: &ctx->ctrl_handler); |
2089 | return err; |
2090 | } |
2091 | |
2092 | err = v4l2_ctrl_handler_setup(hdl: &ctx->ctrl_handler); |
2093 | if (err) |
2094 | v4l2_ctrl_handler_free(hdl: &ctx->ctrl_handler); |
2095 | return err; |
2096 | } |
2097 | |
2098 | static int mxc_jpeg_open(struct file *file) |
2099 | { |
2100 | struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file); |
2101 | struct video_device *mxc_vfd = video_devdata(file); |
2102 | struct device *dev = mxc_jpeg->dev; |
2103 | struct mxc_jpeg_ctx *ctx; |
2104 | int ret = 0; |
2105 | |
2106 | ctx = kzalloc(size: sizeof(*ctx), GFP_KERNEL); |
2107 | if (!ctx) |
2108 | return -ENOMEM; |
2109 | |
2110 | if (mutex_lock_interruptible(&mxc_jpeg->lock)) { |
2111 | ret = -ERESTARTSYS; |
2112 | goto free; |
2113 | } |
2114 | |
2115 | v4l2_fh_init(fh: &ctx->fh, vdev: mxc_vfd); |
2116 | file->private_data = &ctx->fh; |
2117 | v4l2_fh_add(fh: &ctx->fh); |
2118 | |
2119 | ctx->mxc_jpeg = mxc_jpeg; |
2120 | |
2121 | ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(m2m_dev: mxc_jpeg->m2m_dev, drv_priv: ctx, |
2122 | queue_init: mxc_jpeg_queue_init); |
2123 | |
2124 | if (IS_ERR(ptr: ctx->fh.m2m_ctx)) { |
2125 | ret = PTR_ERR(ptr: ctx->fh.m2m_ctx); |
2126 | goto error; |
2127 | } |
2128 | |
2129 | ret = mxc_jpeg_ctrls_setup(ctx); |
2130 | if (ret) { |
2131 | dev_err(ctx->mxc_jpeg->dev, "failed to setup mxc jpeg controls\n" ); |
2132 | goto err_ctrls_setup; |
2133 | } |
2134 | ctx->fh.ctrl_handler = &ctx->ctrl_handler; |
2135 | mxc_jpeg_set_default_params(ctx); |
2136 | ctx->slot = -1; /* slot not allocated yet */ |
2137 | INIT_DELAYED_WORK(&ctx->task_timer, mxc_jpeg_device_run_timeout); |
2138 | |
2139 | if (mxc_jpeg->mode == MXC_JPEG_DECODE) |
2140 | dev_dbg(dev, "Opened JPEG decoder instance %p\n" , ctx); |
2141 | else |
2142 | dev_dbg(dev, "Opened JPEG encoder instance %p\n" , ctx); |
2143 | mutex_unlock(lock: &mxc_jpeg->lock); |
2144 | |
2145 | return 0; |
2146 | |
2147 | err_ctrls_setup: |
2148 | v4l2_m2m_ctx_release(m2m_ctx: ctx->fh.m2m_ctx); |
2149 | error: |
2150 | v4l2_fh_del(fh: &ctx->fh); |
2151 | v4l2_fh_exit(fh: &ctx->fh); |
2152 | mutex_unlock(lock: &mxc_jpeg->lock); |
2153 | free: |
2154 | kfree(objp: ctx); |
2155 | return ret; |
2156 | } |
2157 | |
2158 | static int mxc_jpeg_querycap(struct file *file, void *priv, |
2159 | struct v4l2_capability *cap) |
2160 | { |
2161 | strscpy(cap->driver, MXC_JPEG_NAME " codec" , sizeof(cap->driver)); |
2162 | strscpy(cap->card, MXC_JPEG_NAME " codec" , sizeof(cap->card)); |
2163 | cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; |
2164 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
2165 | |
2166 | return 0; |
2167 | } |
2168 | |
2169 | static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, |
2170 | struct v4l2_fmtdesc *f) |
2171 | { |
2172 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh: priv); |
2173 | struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, type: f->type); |
2174 | |
2175 | if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) { |
2176 | return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, |
2177 | MXC_JPEG_FMT_TYPE_ENC); |
2178 | } else if (!ctx->header_parsed) { |
2179 | return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, |
2180 | MXC_JPEG_FMT_TYPE_RAW); |
2181 | } else { |
2182 | /* For the decoder CAPTURE queue, only enumerate the raw formats |
2183 | * supported for the format currently active on OUTPUT |
2184 | * (more precisely what was propagated on capture queue |
2185 | * after jpeg parse on the output buffer) |
2186 | */ |
2187 | int ret = -EINVAL; |
2188 | const struct mxc_jpeg_fmt *sibling; |
2189 | |
2190 | switch (f->index) { |
2191 | case 0: |
2192 | f->pixelformat = q_data->fmt->fourcc; |
2193 | ret = 0; |
2194 | break; |
2195 | case 1: |
2196 | sibling = mxc_jpeg_get_sibling_format(fmt: q_data->fmt); |
2197 | if (sibling) { |
2198 | f->pixelformat = sibling->fourcc; |
2199 | ret = 0; |
2200 | } |
2201 | break; |
2202 | default: |
2203 | break; |
2204 | } |
2205 | return ret; |
2206 | } |
2207 | } |
2208 | |
2209 | static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv, |
2210 | struct v4l2_fmtdesc *f) |
2211 | { |
2212 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh: priv); |
2213 | u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? MXC_JPEG_FMT_TYPE_ENC : |
2214 | MXC_JPEG_FMT_TYPE_RAW; |
2215 | int ret; |
2216 | |
2217 | ret = enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, type); |
2218 | if (ret) |
2219 | return ret; |
2220 | if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) |
2221 | f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION; |
2222 | return 0; |
2223 | } |
2224 | |
2225 | static u32 mxc_jpeg_get_fmt_type(struct mxc_jpeg_ctx *ctx, u32 type) |
2226 | { |
2227 | if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) |
2228 | return V4L2_TYPE_IS_OUTPUT(type) ? MXC_JPEG_FMT_TYPE_ENC : MXC_JPEG_FMT_TYPE_RAW; |
2229 | else |
2230 | return V4L2_TYPE_IS_CAPTURE(type) ? MXC_JPEG_FMT_TYPE_ENC : MXC_JPEG_FMT_TYPE_RAW; |
2231 | } |
2232 | |
2233 | static u32 mxc_jpeg_get_default_fourcc(struct mxc_jpeg_ctx *ctx, u32 type) |
2234 | { |
2235 | if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) |
2236 | return V4L2_TYPE_IS_OUTPUT(type) ? V4L2_PIX_FMT_JPEG : MXC_JPEG_DEFAULT_PFMT; |
2237 | else |
2238 | return V4L2_TYPE_IS_CAPTURE(type) ? V4L2_PIX_FMT_JPEG : MXC_JPEG_DEFAULT_PFMT; |
2239 | } |
2240 | |
2241 | static u32 mxc_jpeg_try_fourcc(struct mxc_jpeg_ctx *ctx, u32 fourcc) |
2242 | { |
2243 | const struct mxc_jpeg_fmt *sibling; |
2244 | struct mxc_jpeg_q_data *q_data_cap; |
2245 | |
2246 | if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE) |
2247 | return fourcc; |
2248 | if (!ctx->header_parsed) |
2249 | return fourcc; |
2250 | |
2251 | q_data_cap = &ctx->cap_q; |
2252 | if (q_data_cap->fmt->fourcc == fourcc) |
2253 | return fourcc; |
2254 | |
2255 | sibling = mxc_jpeg_get_sibling_format(fmt: q_data_cap->fmt); |
2256 | if (sibling && sibling->fourcc == fourcc) |
2257 | return sibling->fourcc; |
2258 | |
2259 | return q_data_cap->fmt->fourcc; |
2260 | } |
2261 | |
2262 | static int mxc_jpeg_try_fmt(struct v4l2_format *f, |
2263 | struct mxc_jpeg_ctx *ctx, struct mxc_jpeg_q_data *q_data) |
2264 | { |
2265 | const struct mxc_jpeg_fmt *fmt; |
2266 | struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; |
2267 | struct v4l2_plane_pix_format *pfmt; |
2268 | u32 fourcc = f->fmt.pix_mp.pixelformat; |
2269 | u32 w = (pix_mp->width < MXC_JPEG_MAX_WIDTH) ? |
2270 | pix_mp->width : MXC_JPEG_MAX_WIDTH; |
2271 | u32 h = (pix_mp->height < MXC_JPEG_MAX_HEIGHT) ? |
2272 | pix_mp->height : MXC_JPEG_MAX_HEIGHT; |
2273 | int i; |
2274 | |
2275 | fmt = mxc_jpeg_find_format(pixelformat: fourcc); |
2276 | if (!fmt || fmt->flags != mxc_jpeg_get_fmt_type(ctx, type: f->type)) { |
2277 | dev_warn(ctx->mxc_jpeg->dev, "Format not supported: %c%c%c%c, use the default.\n" , |
2278 | (fourcc & 0xff), |
2279 | (fourcc >> 8) & 0xff, |
2280 | (fourcc >> 16) & 0xff, |
2281 | (fourcc >> 24) & 0xff); |
2282 | fourcc = mxc_jpeg_get_default_fourcc(ctx, type: f->type); |
2283 | fmt = mxc_jpeg_find_format(pixelformat: fourcc); |
2284 | if (!fmt) |
2285 | return -EINVAL; |
2286 | f->fmt.pix_mp.pixelformat = fourcc; |
2287 | } |
2288 | q_data->fmt = fmt; |
2289 | |
2290 | memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved)); |
2291 | pix_mp->field = V4L2_FIELD_NONE; |
2292 | pix_mp->num_planes = fmt->mem_planes; |
2293 | pix_mp->pixelformat = fmt->fourcc; |
2294 | |
2295 | q_data->w = w; |
2296 | q_data->h = h; |
2297 | q_data->w_adjusted = w; |
2298 | q_data->h_adjusted = h; |
2299 | v4l_bound_align_image(width: &q_data->w_adjusted, |
2300 | wmin: w, /* adjust upwards*/ |
2301 | MXC_JPEG_MAX_WIDTH, |
2302 | walign: fmt->h_align, |
2303 | height: &q_data->h_adjusted, |
2304 | hmin: h, /* adjust upwards*/ |
2305 | MXC_JPEG_MAX_HEIGHT, |
2306 | halign: fmt->v_align, |
2307 | salign: 0); |
2308 | for (i = 0; i < pix_mp->num_planes; i++) { |
2309 | pfmt = &pix_mp->plane_fmt[i]; |
2310 | q_data->bytesperline[i] = pfmt->bytesperline; |
2311 | q_data->sizeimage[i] = pfmt->sizeimage; |
2312 | } |
2313 | |
2314 | /* calculate bytesperline & sizeimage */ |
2315 | mxc_jpeg_bytesperline(q: q_data, precision: fmt->precision); |
2316 | mxc_jpeg_sizeimage(q: q_data); |
2317 | |
2318 | /* adjust user format according to our calculations */ |
2319 | for (i = 0; i < pix_mp->num_planes; i++) { |
2320 | pfmt = &pix_mp->plane_fmt[i]; |
2321 | memset(pfmt->reserved, 0, sizeof(pfmt->reserved)); |
2322 | pfmt->bytesperline = q_data->bytesperline[i]; |
2323 | pfmt->sizeimage = mxc_jpeg_get_plane_size(q_data, plane_no: i); |
2324 | } |
2325 | |
2326 | /* fix colorspace information to sRGB for both output & capture */ |
2327 | pix_mp->colorspace = V4L2_COLORSPACE_SRGB; |
2328 | pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601; |
2329 | pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB; |
2330 | /* |
2331 | * this hardware does not change the range of the samples |
2332 | * but since inside JPEG the YUV quantization is full-range, |
2333 | * this driver will always use full-range for the raw frames, too |
2334 | */ |
2335 | pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE; |
2336 | |
2337 | if (fmt->flags == MXC_JPEG_FMT_TYPE_RAW) { |
2338 | q_data->crop.left = 0; |
2339 | q_data->crop.top = 0; |
2340 | q_data->crop.width = q_data->w; |
2341 | q_data->crop.height = q_data->h; |
2342 | } |
2343 | |
2344 | pix_mp->width = q_data->w_adjusted; |
2345 | pix_mp->height = q_data->h_adjusted; |
2346 | |
2347 | return 0; |
2348 | } |
2349 | |
2350 | static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv, |
2351 | struct v4l2_format *f) |
2352 | { |
2353 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh: priv); |
2354 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
2355 | struct device *dev = jpeg->dev; |
2356 | struct mxc_jpeg_q_data tmp_q; |
2357 | |
2358 | if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) { |
2359 | dev_err(dev, "TRY_FMT with Invalid type: %d\n" , f->type); |
2360 | return -EINVAL; |
2361 | } |
2362 | |
2363 | if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(f->type)) |
2364 | f->fmt.pix_mp.pixelformat = mxc_jpeg_try_fourcc(ctx, fourcc: f->fmt.pix_mp.pixelformat); |
2365 | |
2366 | return mxc_jpeg_try_fmt(f, ctx, q_data: &tmp_q); |
2367 | } |
2368 | |
2369 | static int mxc_jpeg_try_fmt_vid_out(struct file *file, void *priv, |
2370 | struct v4l2_format *f) |
2371 | { |
2372 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh: priv); |
2373 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
2374 | struct device *dev = jpeg->dev; |
2375 | struct mxc_jpeg_q_data tmp_q; |
2376 | |
2377 | if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) { |
2378 | dev_err(dev, "TRY_FMT with Invalid type: %d\n" , f->type); |
2379 | return -EINVAL; |
2380 | } |
2381 | |
2382 | return mxc_jpeg_try_fmt(f, ctx, q_data: &tmp_q); |
2383 | } |
2384 | |
2385 | static void mxc_jpeg_s_parsed_fmt(struct mxc_jpeg_ctx *ctx, struct v4l2_format *f) |
2386 | { |
2387 | struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; |
2388 | struct mxc_jpeg_q_data *q_data_cap; |
2389 | |
2390 | if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE || !V4L2_TYPE_IS_CAPTURE(f->type)) |
2391 | return; |
2392 | if (!ctx->header_parsed) |
2393 | return; |
2394 | |
2395 | q_data_cap = mxc_jpeg_get_q_data(ctx, type: f->type); |
2396 | pix_mp->pixelformat = mxc_jpeg_try_fourcc(ctx, fourcc: pix_mp->pixelformat); |
2397 | pix_mp->width = q_data_cap->w; |
2398 | pix_mp->height = q_data_cap->h; |
2399 | } |
2400 | |
2401 | static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx, |
2402 | struct v4l2_format *f) |
2403 | { |
2404 | struct vb2_queue *vq; |
2405 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
2406 | |
2407 | vq = v4l2_m2m_get_vq(m2m_ctx: ctx->fh.m2m_ctx, type: f->type); |
2408 | if (!vq) |
2409 | return -EINVAL; |
2410 | |
2411 | if (vb2_is_busy(q: vq)) { |
2412 | v4l2_err(&jpeg->v4l2_dev, "queue busy\n" ); |
2413 | return -EBUSY; |
2414 | } |
2415 | |
2416 | mxc_jpeg_s_parsed_fmt(ctx, f); |
2417 | |
2418 | return mxc_jpeg_try_fmt(f, ctx, q_data: mxc_jpeg_get_q_data(ctx, type: f->type)); |
2419 | } |
2420 | |
2421 | static int mxc_jpeg_s_fmt_vid_cap(struct file *file, void *priv, |
2422 | struct v4l2_format *f) |
2423 | { |
2424 | return mxc_jpeg_s_fmt(ctx: mxc_jpeg_fh_to_ctx(fh: priv), f); |
2425 | } |
2426 | |
2427 | static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv, |
2428 | struct v4l2_format *f) |
2429 | { |
2430 | int ret; |
2431 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh: priv); |
2432 | struct vb2_queue *dst_vq; |
2433 | struct mxc_jpeg_q_data *q_data_cap; |
2434 | enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
2435 | struct v4l2_format fc; |
2436 | |
2437 | ret = mxc_jpeg_s_fmt(ctx: mxc_jpeg_fh_to_ctx(fh: priv), f); |
2438 | if (ret) |
2439 | return ret; |
2440 | |
2441 | if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE) |
2442 | return 0; |
2443 | |
2444 | dst_vq = v4l2_m2m_get_vq(m2m_ctx: ctx->fh.m2m_ctx, type: cap_type); |
2445 | if (!dst_vq) |
2446 | return -EINVAL; |
2447 | |
2448 | if (vb2_is_busy(q: dst_vq)) |
2449 | return 0; |
2450 | |
2451 | q_data_cap = mxc_jpeg_get_q_data(ctx, type: cap_type); |
2452 | if (q_data_cap->w == f->fmt.pix_mp.width && q_data_cap->h == f->fmt.pix_mp.height) |
2453 | return 0; |
2454 | memset(&fc, 0, sizeof(fc)); |
2455 | fc.type = cap_type; |
2456 | fc.fmt.pix_mp.pixelformat = q_data_cap->fmt->fourcc; |
2457 | fc.fmt.pix_mp.width = f->fmt.pix_mp.width; |
2458 | fc.fmt.pix_mp.height = f->fmt.pix_mp.height; |
2459 | |
2460 | return mxc_jpeg_s_fmt_vid_cap(file, priv, f: &fc); |
2461 | } |
2462 | |
2463 | static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv, |
2464 | struct v4l2_format *f) |
2465 | { |
2466 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh: priv); |
2467 | struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; |
2468 | struct device *dev = jpeg->dev; |
2469 | struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; |
2470 | struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, type: f->type); |
2471 | int i; |
2472 | |
2473 | if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) { |
2474 | dev_err(dev, "G_FMT with Invalid type: %d\n" , f->type); |
2475 | return -EINVAL; |
2476 | } |
2477 | |
2478 | pix_mp->pixelformat = q_data->fmt->fourcc; |
2479 | pix_mp->width = q_data->w; |
2480 | pix_mp->height = q_data->h; |
2481 | pix_mp->field = V4L2_FIELD_NONE; |
2482 | if (q_data->fmt->flags == MXC_JPEG_FMT_TYPE_RAW) { |
2483 | pix_mp->width = q_data->w_adjusted; |
2484 | pix_mp->height = q_data->h_adjusted; |
2485 | } |
2486 | |
2487 | /* fix colorspace information to sRGB for both output & capture */ |
2488 | pix_mp->colorspace = V4L2_COLORSPACE_SRGB; |
2489 | pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601; |
2490 | pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB; |
2491 | pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE; |
2492 | |
2493 | pix_mp->num_planes = q_data->fmt->mem_planes; |
2494 | for (i = 0; i < pix_mp->num_planes; i++) { |
2495 | pix_mp->plane_fmt[i].bytesperline = q_data->bytesperline[i]; |
2496 | pix_mp->plane_fmt[i].sizeimage = mxc_jpeg_get_plane_size(q_data, plane_no: i); |
2497 | } |
2498 | |
2499 | return 0; |
2500 | } |
2501 | |
2502 | static int mxc_jpeg_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) |
2503 | { |
2504 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); |
2505 | struct mxc_jpeg_q_data *q_data_cap; |
2506 | |
2507 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
2508 | return -EINVAL; |
2509 | |
2510 | q_data_cap = mxc_jpeg_get_q_data(ctx, type: s->type); |
2511 | |
2512 | switch (s->target) { |
2513 | case V4L2_SEL_TGT_COMPOSE: |
2514 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: |
2515 | s->r = q_data_cap->crop; |
2516 | break; |
2517 | case V4L2_SEL_TGT_COMPOSE_PADDED: |
2518 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: |
2519 | s->r.left = 0; |
2520 | s->r.top = 0; |
2521 | s->r.width = q_data_cap->w_adjusted; |
2522 | s->r.height = q_data_cap->h_adjusted; |
2523 | break; |
2524 | default: |
2525 | return -EINVAL; |
2526 | } |
2527 | |
2528 | return 0; |
2529 | } |
2530 | |
2531 | static int mxc_jpeg_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) |
2532 | { |
2533 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); |
2534 | struct mxc_jpeg_q_data *q_data_out; |
2535 | |
2536 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
2537 | return -EINVAL; |
2538 | |
2539 | q_data_out = mxc_jpeg_get_q_data(ctx, type: s->type); |
2540 | |
2541 | switch (s->target) { |
2542 | case V4L2_SEL_TGT_CROP_DEFAULT: |
2543 | case V4L2_SEL_TGT_CROP_BOUNDS: |
2544 | s->r.left = 0; |
2545 | s->r.top = 0; |
2546 | s->r.width = q_data_out->w; |
2547 | s->r.height = q_data_out->h; |
2548 | break; |
2549 | case V4L2_SEL_TGT_CROP: |
2550 | s->r = q_data_out->crop; |
2551 | break; |
2552 | default: |
2553 | return -EINVAL; |
2554 | } |
2555 | |
2556 | return 0; |
2557 | } |
2558 | |
2559 | static int mxc_jpeg_g_selection(struct file *file, void *fh, struct v4l2_selection *s) |
2560 | { |
2561 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); |
2562 | |
2563 | if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) |
2564 | return mxc_jpeg_dec_g_selection(file, fh, s); |
2565 | else |
2566 | return mxc_jpeg_enc_g_selection(file, fh, s); |
2567 | } |
2568 | |
2569 | static int mxc_jpeg_s_selection(struct file *file, void *fh, struct v4l2_selection *s) |
2570 | { |
2571 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); |
2572 | struct mxc_jpeg_q_data *q_data_out; |
2573 | |
2574 | if (ctx->mxc_jpeg->mode != MXC_JPEG_ENCODE) |
2575 | return -ENOTTY; |
2576 | |
2577 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
2578 | return -EINVAL; |
2579 | if (s->target != V4L2_SEL_TGT_CROP) |
2580 | return -EINVAL; |
2581 | |
2582 | q_data_out = mxc_jpeg_get_q_data(ctx, type: s->type); |
2583 | if (s->r.left || s->r.top) |
2584 | return -EINVAL; |
2585 | if (s->r.width > q_data_out->w || s->r.height > q_data_out->h) |
2586 | return -EINVAL; |
2587 | |
2588 | q_data_out->crop.left = 0; |
2589 | q_data_out->crop.top = 0; |
2590 | q_data_out->crop.width = s->r.width; |
2591 | q_data_out->crop.height = s->r.height; |
2592 | |
2593 | return 0; |
2594 | } |
2595 | |
2596 | static int mxc_jpeg_subscribe_event(struct v4l2_fh *fh, |
2597 | const struct v4l2_event_subscription *sub) |
2598 | { |
2599 | switch (sub->type) { |
2600 | case V4L2_EVENT_EOS: |
2601 | return v4l2_event_subscribe(fh, sub, elems: 0, NULL); |
2602 | case V4L2_EVENT_SOURCE_CHANGE: |
2603 | return v4l2_src_change_event_subscribe(fh, sub); |
2604 | case V4L2_EVENT_CTRL: |
2605 | return v4l2_ctrl_subscribe_event(fh, sub); |
2606 | default: |
2607 | return -EINVAL; |
2608 | } |
2609 | } |
2610 | |
2611 | static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = { |
2612 | .vidioc_querycap = mxc_jpeg_querycap, |
2613 | .vidioc_enum_fmt_vid_cap = mxc_jpeg_enum_fmt_vid_cap, |
2614 | .vidioc_enum_fmt_vid_out = mxc_jpeg_enum_fmt_vid_out, |
2615 | |
2616 | .vidioc_try_fmt_vid_cap_mplane = mxc_jpeg_try_fmt_vid_cap, |
2617 | .vidioc_try_fmt_vid_out_mplane = mxc_jpeg_try_fmt_vid_out, |
2618 | |
2619 | .vidioc_s_fmt_vid_cap_mplane = mxc_jpeg_s_fmt_vid_cap, |
2620 | .vidioc_s_fmt_vid_out_mplane = mxc_jpeg_s_fmt_vid_out, |
2621 | |
2622 | .vidioc_g_fmt_vid_cap_mplane = mxc_jpeg_g_fmt_vid, |
2623 | .vidioc_g_fmt_vid_out_mplane = mxc_jpeg_g_fmt_vid, |
2624 | |
2625 | .vidioc_g_selection = mxc_jpeg_g_selection, |
2626 | .vidioc_s_selection = mxc_jpeg_s_selection, |
2627 | |
2628 | .vidioc_subscribe_event = mxc_jpeg_subscribe_event, |
2629 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
2630 | |
2631 | .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, |
2632 | .vidioc_decoder_cmd = mxc_jpeg_decoder_cmd, |
2633 | .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, |
2634 | .vidioc_encoder_cmd = mxc_jpeg_encoder_cmd, |
2635 | |
2636 | .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, |
2637 | .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, |
2638 | |
2639 | .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, |
2640 | .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, |
2641 | .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, |
2642 | .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, |
2643 | .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, |
2644 | .vidioc_streamon = v4l2_m2m_ioctl_streamon, |
2645 | .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, |
2646 | }; |
2647 | |
2648 | static int mxc_jpeg_release(struct file *file) |
2649 | { |
2650 | struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file); |
2651 | struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh: file->private_data); |
2652 | struct device *dev = mxc_jpeg->dev; |
2653 | |
2654 | mutex_lock(&mxc_jpeg->lock); |
2655 | if (mxc_jpeg->mode == MXC_JPEG_DECODE) |
2656 | dev_dbg(dev, "Release JPEG decoder instance on slot %d." , |
2657 | ctx->slot); |
2658 | else |
2659 | dev_dbg(dev, "Release JPEG encoder instance on slot %d." , |
2660 | ctx->slot); |
2661 | v4l2_ctrl_handler_free(hdl: &ctx->ctrl_handler); |
2662 | v4l2_m2m_ctx_release(m2m_ctx: ctx->fh.m2m_ctx); |
2663 | v4l2_fh_del(fh: &ctx->fh); |
2664 | v4l2_fh_exit(fh: &ctx->fh); |
2665 | kfree(objp: ctx); |
2666 | mutex_unlock(lock: &mxc_jpeg->lock); |
2667 | |
2668 | return 0; |
2669 | } |
2670 | |
2671 | static const struct v4l2_file_operations mxc_jpeg_fops = { |
2672 | .owner = THIS_MODULE, |
2673 | .open = mxc_jpeg_open, |
2674 | .release = mxc_jpeg_release, |
2675 | .poll = v4l2_m2m_fop_poll, |
2676 | .unlocked_ioctl = video_ioctl2, |
2677 | .mmap = v4l2_m2m_fop_mmap, |
2678 | }; |
2679 | |
2680 | static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = { |
2681 | .job_ready = mxc_jpeg_job_ready, |
2682 | .device_run = mxc_jpeg_device_run, |
2683 | }; |
2684 | |
2685 | static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg) |
2686 | { |
2687 | int i; |
2688 | |
2689 | for (i = 0; i < jpeg->num_domains; i++) { |
2690 | if (jpeg->pd_link[i] && !IS_ERR(ptr: jpeg->pd_link[i])) |
2691 | device_link_del(link: jpeg->pd_link[i]); |
2692 | if (jpeg->pd_dev[i] && !IS_ERR(ptr: jpeg->pd_dev[i])) |
2693 | dev_pm_domain_detach(dev: jpeg->pd_dev[i], power_off: true); |
2694 | jpeg->pd_dev[i] = NULL; |
2695 | jpeg->pd_link[i] = NULL; |
2696 | } |
2697 | } |
2698 | |
2699 | static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg) |
2700 | { |
2701 | struct device *dev = jpeg->dev; |
2702 | struct device_node *np = jpeg->pdev->dev.of_node; |
2703 | int i; |
2704 | int ret; |
2705 | |
2706 | jpeg->num_domains = of_count_phandle_with_args(np, list_name: "power-domains" , |
2707 | cells_name: "#power-domain-cells" ); |
2708 | if (jpeg->num_domains < 0) { |
2709 | dev_err(dev, "No power domains defined for jpeg node\n" ); |
2710 | return jpeg->num_domains; |
2711 | } |
2712 | if (jpeg->num_domains == 1) { |
2713 | /* genpd_dev_pm_attach() attach automatically if power domains count is 1 */ |
2714 | jpeg->num_domains = 0; |
2715 | return 0; |
2716 | } |
2717 | |
2718 | jpeg->pd_dev = devm_kmalloc_array(dev, n: jpeg->num_domains, |
2719 | size: sizeof(*jpeg->pd_dev), GFP_KERNEL); |
2720 | if (!jpeg->pd_dev) |
2721 | return -ENOMEM; |
2722 | |
2723 | jpeg->pd_link = devm_kmalloc_array(dev, n: jpeg->num_domains, |
2724 | size: sizeof(*jpeg->pd_link), GFP_KERNEL); |
2725 | if (!jpeg->pd_link) |
2726 | return -ENOMEM; |
2727 | |
2728 | for (i = 0; i < jpeg->num_domains; i++) { |
2729 | jpeg->pd_dev[i] = dev_pm_domain_attach_by_id(dev, index: i); |
2730 | if (IS_ERR(ptr: jpeg->pd_dev[i])) { |
2731 | ret = PTR_ERR(ptr: jpeg->pd_dev[i]); |
2732 | goto fail; |
2733 | } |
2734 | |
2735 | jpeg->pd_link[i] = device_link_add(consumer: dev, supplier: jpeg->pd_dev[i], |
2736 | DL_FLAG_STATELESS | |
2737 | DL_FLAG_PM_RUNTIME); |
2738 | if (!jpeg->pd_link[i]) { |
2739 | ret = -EINVAL; |
2740 | goto fail; |
2741 | } |
2742 | } |
2743 | |
2744 | return 0; |
2745 | fail: |
2746 | mxc_jpeg_detach_pm_domains(jpeg); |
2747 | return ret; |
2748 | } |
2749 | |
2750 | static int mxc_jpeg_probe(struct platform_device *pdev) |
2751 | { |
2752 | struct mxc_jpeg_dev *jpeg; |
2753 | struct device *dev = &pdev->dev; |
2754 | int dec_irq; |
2755 | int ret; |
2756 | int mode; |
2757 | const struct of_device_id *of_id; |
2758 | |
2759 | of_id = of_match_node(matches: mxc_jpeg_match, node: dev->of_node); |
2760 | if (!of_id) |
2761 | return -ENODEV; |
2762 | mode = *(const int *)of_id->data; |
2763 | |
2764 | jpeg = devm_kzalloc(dev, size: sizeof(struct mxc_jpeg_dev), GFP_KERNEL); |
2765 | if (!jpeg) |
2766 | return -ENOMEM; |
2767 | |
2768 | mutex_init(&jpeg->lock); |
2769 | spin_lock_init(&jpeg->hw_lock); |
2770 | |
2771 | ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); |
2772 | if (ret) { |
2773 | dev_err(&pdev->dev, "No suitable DMA available.\n" ); |
2774 | goto err_irq; |
2775 | } |
2776 | |
2777 | jpeg->base_reg = devm_platform_ioremap_resource(pdev, index: 0); |
2778 | if (IS_ERR(ptr: jpeg->base_reg)) |
2779 | return PTR_ERR(ptr: jpeg->base_reg); |
2780 | |
2781 | ret = of_property_read_u32_index(np: pdev->dev.of_node, propname: "slot" , index: 0, out_value: &jpeg->slot_data.slot); |
2782 | if (ret) |
2783 | jpeg->slot_data.slot = 0; |
2784 | dev_info(&pdev->dev, "choose slot %d\n" , jpeg->slot_data.slot); |
2785 | dec_irq = platform_get_irq(pdev, 0); |
2786 | if (dec_irq < 0) { |
2787 | ret = dec_irq; |
2788 | goto err_irq; |
2789 | } |
2790 | ret = devm_request_irq(dev: &pdev->dev, irq: dec_irq, handler: mxc_jpeg_dec_irq, |
2791 | irqflags: 0, devname: pdev->name, dev_id: jpeg); |
2792 | if (ret) { |
2793 | dev_err(&pdev->dev, "Failed to request irq %d (%d)\n" , |
2794 | dec_irq, ret); |
2795 | goto err_irq; |
2796 | } |
2797 | |
2798 | jpeg->pdev = pdev; |
2799 | jpeg->dev = dev; |
2800 | jpeg->mode = mode; |
2801 | |
2802 | /* Get clocks */ |
2803 | ret = devm_clk_bulk_get_all(dev: &pdev->dev, clks: &jpeg->clks); |
2804 | if (ret < 0) { |
2805 | dev_err(dev, "failed to get clock\n" ); |
2806 | goto err_clk; |
2807 | } |
2808 | jpeg->num_clks = ret; |
2809 | |
2810 | ret = mxc_jpeg_attach_pm_domains(jpeg); |
2811 | if (ret < 0) { |
2812 | dev_err(dev, "failed to attach power domains %d\n" , ret); |
2813 | goto err_clk; |
2814 | } |
2815 | |
2816 | /* v4l2 */ |
2817 | ret = v4l2_device_register(dev, v4l2_dev: &jpeg->v4l2_dev); |
2818 | if (ret) { |
2819 | dev_err(dev, "failed to register v4l2 device\n" ); |
2820 | goto err_register; |
2821 | } |
2822 | jpeg->m2m_dev = v4l2_m2m_init(m2m_ops: &mxc_jpeg_m2m_ops); |
2823 | if (IS_ERR(ptr: jpeg->m2m_dev)) { |
2824 | dev_err(dev, "failed to register v4l2 device\n" ); |
2825 | ret = PTR_ERR(ptr: jpeg->m2m_dev); |
2826 | goto err_m2m; |
2827 | } |
2828 | |
2829 | jpeg->dec_vdev = video_device_alloc(); |
2830 | if (!jpeg->dec_vdev) { |
2831 | dev_err(dev, "failed to register v4l2 device\n" ); |
2832 | ret = -ENOMEM; |
2833 | goto err_vdev_alloc; |
2834 | } |
2835 | if (mode == MXC_JPEG_ENCODE) |
2836 | snprintf(buf: jpeg->dec_vdev->name, |
2837 | size: sizeof(jpeg->dec_vdev->name), |
2838 | fmt: "%s-enc" , MXC_JPEG_NAME); |
2839 | else |
2840 | snprintf(buf: jpeg->dec_vdev->name, |
2841 | size: sizeof(jpeg->dec_vdev->name), |
2842 | fmt: "%s-dec" , MXC_JPEG_NAME); |
2843 | |
2844 | jpeg->dec_vdev->fops = &mxc_jpeg_fops; |
2845 | jpeg->dec_vdev->ioctl_ops = &mxc_jpeg_ioctl_ops; |
2846 | jpeg->dec_vdev->minor = -1; |
2847 | jpeg->dec_vdev->release = video_device_release; |
2848 | jpeg->dec_vdev->lock = &jpeg->lock; /* lock for ioctl serialization */ |
2849 | jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev; |
2850 | jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M; |
2851 | jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING | |
2852 | V4L2_CAP_VIDEO_M2M_MPLANE; |
2853 | if (mode == MXC_JPEG_ENCODE) { |
2854 | v4l2_disable_ioctl(vdev: jpeg->dec_vdev, VIDIOC_DECODER_CMD); |
2855 | v4l2_disable_ioctl(vdev: jpeg->dec_vdev, VIDIOC_TRY_DECODER_CMD); |
2856 | } else { |
2857 | v4l2_disable_ioctl(vdev: jpeg->dec_vdev, VIDIOC_ENCODER_CMD); |
2858 | v4l2_disable_ioctl(vdev: jpeg->dec_vdev, VIDIOC_TRY_ENCODER_CMD); |
2859 | } |
2860 | ret = video_register_device(vdev: jpeg->dec_vdev, type: VFL_TYPE_VIDEO, nr: -1); |
2861 | if (ret) { |
2862 | dev_err(dev, "failed to register video device\n" ); |
2863 | goto err_vdev_register; |
2864 | } |
2865 | video_set_drvdata(vdev: jpeg->dec_vdev, data: jpeg); |
2866 | if (mode == MXC_JPEG_ENCODE) |
2867 | v4l2_info(&jpeg->v4l2_dev, |
2868 | "encoder device registered as /dev/video%d (%d,%d)\n" , |
2869 | jpeg->dec_vdev->num, VIDEO_MAJOR, |
2870 | jpeg->dec_vdev->minor); |
2871 | else |
2872 | v4l2_info(&jpeg->v4l2_dev, |
2873 | "decoder device registered as /dev/video%d (%d,%d)\n" , |
2874 | jpeg->dec_vdev->num, VIDEO_MAJOR, |
2875 | jpeg->dec_vdev->minor); |
2876 | |
2877 | platform_set_drvdata(pdev, data: jpeg); |
2878 | pm_runtime_enable(dev); |
2879 | |
2880 | return 0; |
2881 | |
2882 | err_vdev_register: |
2883 | video_device_release(vdev: jpeg->dec_vdev); |
2884 | |
2885 | err_vdev_alloc: |
2886 | v4l2_m2m_release(m2m_dev: jpeg->m2m_dev); |
2887 | |
2888 | err_m2m: |
2889 | v4l2_device_unregister(v4l2_dev: &jpeg->v4l2_dev); |
2890 | |
2891 | err_register: |
2892 | mxc_jpeg_detach_pm_domains(jpeg); |
2893 | |
2894 | err_irq: |
2895 | err_clk: |
2896 | return ret; |
2897 | } |
2898 | |
2899 | #ifdef CONFIG_PM |
2900 | static int mxc_jpeg_runtime_resume(struct device *dev) |
2901 | { |
2902 | struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev); |
2903 | int ret; |
2904 | |
2905 | ret = clk_bulk_prepare_enable(num_clks: jpeg->num_clks, clks: jpeg->clks); |
2906 | if (ret < 0) { |
2907 | dev_err(dev, "failed to enable clock\n" ); |
2908 | return ret; |
2909 | } |
2910 | |
2911 | return 0; |
2912 | } |
2913 | |
2914 | static int mxc_jpeg_runtime_suspend(struct device *dev) |
2915 | { |
2916 | struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev); |
2917 | |
2918 | clk_bulk_disable_unprepare(num_clks: jpeg->num_clks, clks: jpeg->clks); |
2919 | |
2920 | return 0; |
2921 | } |
2922 | #endif |
2923 | |
2924 | #ifdef CONFIG_PM_SLEEP |
2925 | static int mxc_jpeg_suspend(struct device *dev) |
2926 | { |
2927 | struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev); |
2928 | |
2929 | v4l2_m2m_suspend(m2m_dev: jpeg->m2m_dev); |
2930 | return pm_runtime_force_suspend(dev); |
2931 | } |
2932 | |
2933 | static int mxc_jpeg_resume(struct device *dev) |
2934 | { |
2935 | struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev); |
2936 | int ret; |
2937 | |
2938 | ret = pm_runtime_force_resume(dev); |
2939 | if (ret < 0) |
2940 | return ret; |
2941 | |
2942 | v4l2_m2m_resume(m2m_dev: jpeg->m2m_dev); |
2943 | return ret; |
2944 | } |
2945 | #endif |
2946 | |
2947 | static const struct dev_pm_ops mxc_jpeg_pm_ops = { |
2948 | SET_RUNTIME_PM_OPS(mxc_jpeg_runtime_suspend, |
2949 | mxc_jpeg_runtime_resume, NULL) |
2950 | SET_SYSTEM_SLEEP_PM_OPS(mxc_jpeg_suspend, mxc_jpeg_resume) |
2951 | }; |
2952 | |
2953 | static void mxc_jpeg_remove(struct platform_device *pdev) |
2954 | { |
2955 | struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev); |
2956 | |
2957 | mxc_jpeg_free_slot_data(jpeg); |
2958 | |
2959 | pm_runtime_disable(dev: &pdev->dev); |
2960 | video_unregister_device(vdev: jpeg->dec_vdev); |
2961 | v4l2_m2m_release(m2m_dev: jpeg->m2m_dev); |
2962 | v4l2_device_unregister(v4l2_dev: &jpeg->v4l2_dev); |
2963 | mxc_jpeg_detach_pm_domains(jpeg); |
2964 | } |
2965 | |
2966 | MODULE_DEVICE_TABLE(of, mxc_jpeg_match); |
2967 | |
2968 | static struct platform_driver mxc_jpeg_driver = { |
2969 | .probe = mxc_jpeg_probe, |
2970 | .remove_new = mxc_jpeg_remove, |
2971 | .driver = { |
2972 | .name = "mxc-jpeg" , |
2973 | .of_match_table = mxc_jpeg_match, |
2974 | .pm = &mxc_jpeg_pm_ops, |
2975 | }, |
2976 | }; |
2977 | module_platform_driver(mxc_jpeg_driver); |
2978 | |
2979 | MODULE_AUTHOR("Zhengyu Shen <zhengyu.shen_1@nxp.com>" ); |
2980 | MODULE_AUTHOR("Mirela Rabulea <mirela.rabulea@nxp.com>" ); |
2981 | MODULE_DESCRIPTION("V4L2 driver for i.MX8 QXP/QM JPEG encoder/decoder" ); |
2982 | MODULE_LICENSE("GPL v2" ); |
2983 | |