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
66static 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
266static const int mxc_decode_mode = MXC_JPEG_DECODE;
267static const int mxc_encode_mode = MXC_JPEG_ENCODE;
268
269static 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 */
285static const unsigned char jpeg_soi[] = {
286 0xFF, 0xD8
287};
288
289static 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
296static 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
302static 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
325static 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
364static 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
371static 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
378static 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
442static 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
526static const unsigned char jpeg_dri[] = {
527 0xFF, 0xDD,
528 0x00, 0x04, 0x00, 0x20
529};
530
531static 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
537static 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
551static const unsigned char jpeg_eoi[] = {
552 0xFF, 0xD9
553};
554
555struct 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
568static 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
574static unsigned int debug;
575module_param(debug, int, 0644);
576MODULE_PARM_DESC(debug, "Debug level (0-3)");
577
578static unsigned int hw_timeout = 2000;
579module_param(hw_timeout, int, 0644);
580MODULE_PARM_DESC(hw_timeout, "MXC JPEG hw timeout, the number of milliseconds");
581
582static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision);
583static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q);
584
585static void _bswap16(u16 *a)
586{
587 *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);
588}
589
590static 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
615static 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
620static 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
646static 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
659static 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
687static 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
695static 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
716static 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
727static 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
737static 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
748static 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
755static 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
791skip_alloc:
792 jpeg->slot_data.used = true;
793
794 return true;
795err:
796 dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", jpeg->slot_data.slot);
797
798 return false;
799}
800
801static 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
821static 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
833static 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
853static 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
880static 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
981buffers_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;
987job_unlock:
988 spin_unlock(lock: &jpeg->hw_lock);
989 return IRQ_HANDLED;
990}
991
992static 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
1046static 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
1091static 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
1161static 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
1230static 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
1299static 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
1315static 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
1325static 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
1339static 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
1406static 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
1413static 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
1430static 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));
1518end:
1519 spin_unlock_irqrestore(lock: &ctx->mxc_jpeg->hw_lock, flags);
1520}
1521
1522static 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
1555static 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
1588static 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
1624static 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
1646static 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
1680static 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
1709static bool mxc_jpeg_match_image_format(const struct mxc_jpeg_fmt *fmt,
1710 const struct v4l2_jpeg_header *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
1731static u32 mxc_jpeg_get_image_format(struct device *dev,
1732 const struct v4l2_jpeg_header *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
1755static 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
1796static 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
1817static 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 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
1898static 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
1932end:
1933 v4l2_m2m_buf_queue(m2m_ctx: ctx->fh.m2m_ctx, vbuf);
1934}
1935
1936static 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
1945static 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
1974static 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
1985static 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
2019static 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
2048static 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
2066static const struct v4l2_ctrl_ops mxc_jpeg_ctrl_ops = {
2067 .s_ctrl = mxc_jpeg_s_ctrl,
2068};
2069
2070static 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
2076static 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
2098static 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
2147err_ctrls_setup:
2148 v4l2_m2m_ctx_release(m2m_ctx: ctx->fh.m2m_ctx);
2149error:
2150 v4l2_fh_del(fh: &ctx->fh);
2151 v4l2_fh_exit(fh: &ctx->fh);
2152 mutex_unlock(lock: &mxc_jpeg->lock);
2153free:
2154 kfree(objp: ctx);
2155 return ret;
2156}
2157
2158static 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
2169static 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
2209static 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
2225static 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
2233static 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
2241static 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
2262static 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
2350static 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
2369static 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
2385static 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
2401static 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
2421static 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
2427static 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
2463static 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
2502static 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
2531static 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
2559static 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
2569static 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
2596static 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
2611static 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
2648static 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
2671static 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
2680static 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
2685static 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
2699static 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;
2745fail:
2746 mxc_jpeg_detach_pm_domains(jpeg);
2747 return ret;
2748}
2749
2750static 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
2882err_vdev_register:
2883 video_device_release(vdev: jpeg->dec_vdev);
2884
2885err_vdev_alloc:
2886 v4l2_m2m_release(m2m_dev: jpeg->m2m_dev);
2887
2888err_m2m:
2889 v4l2_device_unregister(v4l2_dev: &jpeg->v4l2_dev);
2890
2891err_register:
2892 mxc_jpeg_detach_pm_domains(jpeg);
2893
2894err_irq:
2895err_clk:
2896 return ret;
2897}
2898
2899#ifdef CONFIG_PM
2900static 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
2914static 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
2925static 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
2933static 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
2947static 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
2953static 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
2966MODULE_DEVICE_TABLE(of, mxc_jpeg_match);
2967
2968static 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};
2977module_platform_driver(mxc_jpeg_driver);
2978
2979MODULE_AUTHOR("Zhengyu Shen <zhengyu.shen_1@nxp.com>");
2980MODULE_AUTHOR("Mirela Rabulea <mirela.rabulea@nxp.com>");
2981MODULE_DESCRIPTION("V4L2 driver for i.MX8 QXP/QM JPEG encoder/decoder");
2982MODULE_LICENSE("GPL v2");
2983

source code of linux/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c