blob: 4ca96cf9def761fbc2f69c4373c873df8ad6603f [file] [log] [blame]
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001// 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, RGB, ARGB, 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/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>
Mirela Rabulea4c2e5152021-10-07 17:30:38 +010052#include <linux/pm_runtime.h>
Mirela Rabulea2db16c62021-03-11 09:53:17 +010053#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
Rikard Falkeborn7ec1c4a2021-06-12 01:42:01 +020066static const struct mxc_jpeg_fmt mxc_formats[] = {
Mirela Rabulea2db16c62021-03-11 09:53:17 +010067 {
68 .name = "JPEG",
69 .fourcc = V4L2_PIX_FMT_JPEG,
70 .subsampling = -1,
71 .nc = -1,
72 .colplanes = 1,
73 .flags = MXC_JPEG_FMT_TYPE_ENC,
74 },
75 {
76 .name = "RGB", /*RGBRGB packed format*/
77 .fourcc = V4L2_PIX_FMT_RGB24,
78 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
79 .nc = 3,
80 .depth = 24,
81 .colplanes = 1,
82 .h_align = 3,
83 .v_align = 3,
84 .flags = MXC_JPEG_FMT_TYPE_RAW,
85 },
86 {
87 .name = "ARGB", /* ARGBARGB packed format */
88 .fourcc = V4L2_PIX_FMT_ARGB32,
89 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
90 .nc = 4,
91 .depth = 32,
92 .colplanes = 1,
93 .h_align = 3,
94 .v_align = 3,
95 .flags = MXC_JPEG_FMT_TYPE_RAW,
96 },
97 {
98 .name = "YUV420", /* 1st plane = Y, 2nd plane = UV */
99 .fourcc = V4L2_PIX_FMT_NV12,
100 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
101 .nc = 3,
102 .depth = 12, /* 6 bytes (4Y + UV) for 4 pixels */
103 .colplanes = 2, /* 1 plane Y, 1 plane UV interleaved */
104 .h_align = 4,
105 .v_align = 4,
106 .flags = MXC_JPEG_FMT_TYPE_RAW,
107 },
108 {
109 .name = "YUV422", /* YUYV */
110 .fourcc = V4L2_PIX_FMT_YUYV,
111 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
112 .nc = 3,
113 .depth = 16,
114 .colplanes = 1,
115 .h_align = 4,
116 .v_align = 3,
117 .flags = MXC_JPEG_FMT_TYPE_RAW,
118 },
119 {
120 .name = "YUV444", /* YUVYUV */
121 .fourcc = V4L2_PIX_FMT_YUV24,
122 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
123 .nc = 3,
124 .depth = 24,
125 .colplanes = 1,
126 .h_align = 3,
127 .v_align = 3,
128 .flags = MXC_JPEG_FMT_TYPE_RAW,
129 },
130 {
131 .name = "Gray", /* Gray (Y8/Y12) or Single Comp */
132 .fourcc = V4L2_PIX_FMT_GREY,
133 .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
134 .nc = 1,
135 .depth = 8,
136 .colplanes = 1,
137 .h_align = 3,
138 .v_align = 3,
139 .flags = MXC_JPEG_FMT_TYPE_RAW,
140 },
141};
142
143#define MXC_JPEG_NUM_FORMATS ARRAY_SIZE(mxc_formats)
144
145static const int mxc_decode_mode = MXC_JPEG_DECODE;
146static const int mxc_encode_mode = MXC_JPEG_ENCODE;
147
148static const struct of_device_id mxc_jpeg_match[] = {
149 {
150 .compatible = "nxp,imx8qxp-jpgdec",
151 .data = &mxc_decode_mode,
152 },
153 {
154 .compatible = "nxp,imx8qxp-jpgenc",
155 .data = &mxc_encode_mode,
156 },
157 { },
158};
159
160/*
161 * default configuration stream, 64x64 yuv422
162 * split by JPEG marker, so it's easier to modify & use
163 */
164static const unsigned char jpeg_soi[] = {
165 0xFF, 0xD8
166};
167
168static const unsigned char jpeg_app0[] = {
169 0xFF, 0xE0,
170 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00,
171 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,
172 0x00, 0x00
173};
174
175static const unsigned char jpeg_app14[] = {
176 0xFF, 0xEE,
177 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65,
178 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00
179};
180
181static const unsigned char jpeg_dqt[] = {
182 0xFF, 0xDB,
183 0x00, 0x84, 0x00, 0x10, 0x0B, 0x0C, 0x0E,
184 0x0C, 0x0A, 0x10, 0x0E, 0x0D, 0x0E, 0x12,
185 0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18,
186 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1D,
187 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33,
188 0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40,
189 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6D,
190 0x51, 0x57, 0x5F, 0x62, 0x67, 0x68, 0x67,
191 0x3E, 0x4D, 0x71, 0x79, 0x70, 0x64, 0x78,
192 0x5C, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12,
193 0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 0x1A,
194 0x2F, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
195 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
196 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
197 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
198 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
199 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
200 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
201 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
202};
203
204static const unsigned char jpeg_sof_maximal[] = {
205 0xFF, 0xC0,
206 0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40,
207 0x04, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01,
208 0x03, 0x11, 0x01, 0x04, 0x11, 0x01
209};
210
211static const unsigned char jpeg_dht[] = {
212 0xFF, 0xC4,
213 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01,
214 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
216 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
217 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01,
218 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05,
219 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
220 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
221 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
222 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91,
223 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15,
224 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72,
225 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19,
226 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
227 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
228 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
229 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
230 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
231 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76,
232 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85,
233 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93,
234 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
235 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
236 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
237 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4,
238 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,
239 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
240 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
241 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
242 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
243 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01,
244 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
246 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
247 0x0B, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,
248 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
249 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
250 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,
251 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13,
252 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
253 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52,
254 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
255 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18,
256 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
257 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43,
258 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
259 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
260 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
261 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77,
262 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85,
263 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93,
264 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
265 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
266 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
267 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4,
268 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,
269 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
270 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
271 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5,
272 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
273};
274
275static const unsigned char jpeg_dri[] = {
276 0xFF, 0xDD,
277 0x00, 0x04, 0x00, 0x20
278};
279
280static const unsigned char jpeg_sos_maximal[] = {
281 0xFF, 0xDA,
282 0x00, 0x0C, 0x04, 0x01, 0x00, 0x02, 0x11, 0x03,
283 0x11, 0x04, 0x11, 0x00, 0x3F, 0x00
284};
285
Mirela Rabulea34acaf62021-09-27 20:56:57 +0200286static const unsigned char jpeg_image_red[] = {
287 0xFC, 0x5F, 0xA2, 0xBF, 0xCA, 0x73, 0xFE, 0xFE,
288 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00,
289 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02,
290 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28,
291 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A,
292 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0,
293 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00,
294 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02,
295 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28,
296 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A,
297 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00
298};
299
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100300static const unsigned char jpeg_eoi[] = {
301 0xFF, 0xD9
302};
303
304struct mxc_jpeg_src_buf {
305 /* common v4l buffer stuff -- must be first */
306 struct vb2_v4l2_buffer b;
307 struct list_head list;
308
309 /* mxc-jpeg specific */
310 bool dht_needed;
311 bool jpeg_parse_error;
312};
313
314static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb)
315{
316 return container_of(to_vb2_v4l2_buffer(vb),
317 struct mxc_jpeg_src_buf, b);
318}
319
320static unsigned int debug;
321module_param(debug, int, 0644);
322MODULE_PARM_DESC(debug, "Debug level (0-3)");
323
324static void _bswap16(u16 *a)
325{
326 *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);
327}
328
329static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf,
330 unsigned long len)
331{
332 unsigned int plane_no;
333 u32 dma_addr;
334 void *vaddr;
335 unsigned long payload;
336
337 if (debug < 3)
338 return;
339
340 for (plane_no = 0; plane_no < buf->num_planes; plane_no++) {
341 payload = vb2_get_plane_payload(buf, plane_no);
342 if (len == 0)
343 len = payload;
344 dma_addr = vb2_dma_contig_plane_dma_addr(buf, plane_no);
345 vaddr = vb2_plane_vaddr(buf, plane_no);
346 v4l2_dbg(3, debug, &jpeg->v4l2_dev,
347 "plane %d (vaddr=%p dma_addr=%x payload=%ld):",
348 plane_no, vaddr, dma_addr, payload);
349 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
350 vaddr, len, false);
351 }
352}
353
354static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh)
355{
356 return container_of(fh, struct mxc_jpeg_ctx, fh);
357}
358
Rikard Falkeborn7ec1c4a2021-06-12 01:42:01 +0200359static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n,
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100360 struct v4l2_fmtdesc *f, u32 type)
361{
362 int i, num = 0;
363
364 for (i = 0; i < n; ++i) {
365 if (mxc_formats[i].flags == type) {
366 /* index-th format of searched type found ? */
367 if (num == f->index)
368 break;
369 /* Correct type but haven't reached our index yet,
370 * just increment per-type index
371 */
372 ++num;
373 }
374 }
375
376 /* Format not found */
377 if (i >= n)
378 return -EINVAL;
379
380 strscpy(f->description, mxc_formats[i].name, sizeof(f->description));
381 f->pixelformat = mxc_formats[i].fourcc;
382
383 return 0;
384}
385
Rikard Falkeborn7ec1c4a2021-06-12 01:42:01 +0200386static const struct mxc_jpeg_fmt *mxc_jpeg_find_format(struct mxc_jpeg_ctx *ctx,
387 u32 pixelformat)
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100388{
389 unsigned int k;
390
391 for (k = 0; k < MXC_JPEG_NUM_FORMATS; k++) {
Rikard Falkeborn7ec1c4a2021-06-12 01:42:01 +0200392 const struct mxc_jpeg_fmt *fmt = &mxc_formats[k];
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100393
394 if (fmt->fourcc == pixelformat)
395 return fmt;
396 }
397 return NULL;
398}
399
400static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc)
401{
402 switch (fourcc) {
403 case V4L2_PIX_FMT_GREY:
404 return MXC_JPEG_GRAY;
405 case V4L2_PIX_FMT_YUYV:
406 return MXC_JPEG_YUV422;
407 case V4L2_PIX_FMT_NV12:
408 return MXC_JPEG_YUV420;
409 case V4L2_PIX_FMT_YUV24:
410 return MXC_JPEG_YUV444;
411 case V4L2_PIX_FMT_RGB24:
412 return MXC_JPEG_RGB;
413 case V4L2_PIX_FMT_ARGB32:
414 return MXC_JPEG_ARGB;
415 default:
416 return MXC_JPEG_INVALID;
417 }
418}
419
420static struct mxc_jpeg_q_data *mxc_jpeg_get_q_data(struct mxc_jpeg_ctx *ctx,
421 enum v4l2_buf_type type)
422{
423 if (V4L2_TYPE_IS_OUTPUT(type))
424 return &ctx->out_q;
425 return &ctx->cap_q;
426}
427
428static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc,
429 struct vb2_buffer *raw_buf,
430 struct vb2_buffer *jpeg_buf, int offset)
431{
432 int img_fmt = desc->stm_ctrl & STM_CTRL_IMAGE_FORMAT_MASK;
433
434 desc->buf_base0 = vb2_dma_contig_plane_dma_addr(raw_buf, 0);
435 desc->buf_base1 = 0;
436 if (img_fmt == STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV420)) {
437 WARN_ON(raw_buf->num_planes < 2);
438 desc->buf_base1 = vb2_dma_contig_plane_dma_addr(raw_buf, 1);
439 }
440 desc->stm_bufbase = vb2_dma_contig_plane_dma_addr(jpeg_buf, 0) +
441 offset;
442}
443
444static void notify_eos(struct mxc_jpeg_ctx *ctx)
445{
446 const struct v4l2_event ev = {
447 .type = V4L2_EVENT_EOS
448 };
449
450 dev_dbg(ctx->mxc_jpeg->dev, "Notify app event EOS reached");
451 v4l2_event_queue_fh(&ctx->fh, &ev);
452}
453
454static void notify_src_chg(struct mxc_jpeg_ctx *ctx)
455{
456 const struct v4l2_event ev = {
457 .type = V4L2_EVENT_SOURCE_CHANGE,
458 .u.src_change.changes =
459 V4L2_EVENT_SRC_CH_RESOLUTION,
460 };
461
462 dev_dbg(ctx->mxc_jpeg->dev, "Notify app event SRC_CH_RESOLUTION");
463 v4l2_event_queue_fh(&ctx->fh, &ev);
464}
465
466static int mxc_get_free_slot(struct mxc_jpeg_slot_data slot_data[], int n)
467{
468 int free_slot = 0;
469
470 while (slot_data[free_slot].used && free_slot < n)
471 free_slot++;
472
473 return free_slot; /* >=n when there are no more free slots */
474}
475
476static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg,
477 unsigned int slot)
478{
479 struct mxc_jpeg_desc *desc;
480 struct mxc_jpeg_desc *cfg_desc;
481 void *cfg_stm;
482
483 if (jpeg->slot_data[slot].desc)
484 goto skip_alloc; /* already allocated, reuse it */
485
486 /* allocate descriptor for decoding/encoding phase */
487 desc = dma_alloc_coherent(jpeg->dev,
488 sizeof(struct mxc_jpeg_desc),
489 &jpeg->slot_data[slot].desc_handle,
490 GFP_ATOMIC);
491 if (!desc)
492 goto err;
493 jpeg->slot_data[slot].desc = desc;
494
495 /* allocate descriptor for configuration phase (encoder only) */
496 cfg_desc = dma_alloc_coherent(jpeg->dev,
497 sizeof(struct mxc_jpeg_desc),
498 &jpeg->slot_data[slot].cfg_desc_handle,
499 GFP_ATOMIC);
500 if (!cfg_desc)
501 goto err;
502 jpeg->slot_data[slot].cfg_desc = cfg_desc;
503
504 /* allocate configuration stream */
505 cfg_stm = dma_alloc_coherent(jpeg->dev,
506 MXC_JPEG_MAX_CFG_STREAM,
507 &jpeg->slot_data[slot].cfg_stream_handle,
508 GFP_ATOMIC);
509 if (!cfg_stm)
510 goto err;
511 jpeg->slot_data[slot].cfg_stream_vaddr = cfg_stm;
512
513skip_alloc:
514 jpeg->slot_data[slot].used = true;
515
516 return true;
517err:
518 dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", slot);
519
520 return false;
521}
522
523static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg,
524 unsigned int slot)
525{
526 if (slot >= MXC_MAX_SLOTS) {
527 dev_err(jpeg->dev, "Invalid slot %d, nothing to free.", slot);
528 return;
529 }
530
531 /* free descriptor for decoding/encoding phase */
532 dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
533 jpeg->slot_data[slot].desc,
534 jpeg->slot_data[slot].desc_handle);
535
536 /* free descriptor for encoder configuration phase / decoder DHT */
537 dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
538 jpeg->slot_data[slot].cfg_desc,
539 jpeg->slot_data[slot].cfg_desc_handle);
540
541 /* free configuration stream */
542 dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
543 jpeg->slot_data[slot].cfg_stream_vaddr,
544 jpeg->slot_data[slot].cfg_stream_handle);
545
546 jpeg->slot_data[slot].used = false;
547}
548
549static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
550{
551 struct mxc_jpeg_dev *jpeg = priv;
552 struct mxc_jpeg_ctx *ctx;
553 void __iomem *reg = jpeg->base_reg;
554 struct device *dev = jpeg->dev;
555 struct vb2_v4l2_buffer *src_buf, *dst_buf;
556 struct mxc_jpeg_src_buf *jpeg_src_buf;
557 enum vb2_buffer_state buf_state;
558 u32 dec_ret, com_status;
559 unsigned long payload;
560 struct mxc_jpeg_q_data *q_data;
561 enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
562 unsigned int slot;
563
564 spin_lock(&jpeg->hw_lock);
565
566 com_status = readl(reg + COM_STATUS);
567 slot = COM_STATUS_CUR_SLOT(com_status);
568 dev_dbg(dev, "Irq %d on slot %d.\n", irq, slot);
569
570 ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
571 if (!ctx) {
572 dev_err(dev,
573 "Instance released before the end of transaction.\n");
574 /* soft reset only resets internal state, not registers */
575 mxc_jpeg_sw_reset(reg);
576 /* clear all interrupts */
577 writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
578 goto job_unlock;
579 }
580
581 if (slot != ctx->slot) {
582 /* TODO investigate when adding multi-instance support */
583 dev_warn(dev, "IRQ slot %d != context slot %d.\n",
584 slot, ctx->slot);
585 goto job_unlock;
586 }
587
588 dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
589 writel(dec_ret, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); /* w1c */
590
591 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
592 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
Mirela Rabulea83f5f062021-09-27 20:56:32 +0200593 if (!dst_buf || !src_buf) {
594 dev_err(dev, "No source or destination buffer.\n");
595 goto job_unlock;
596 }
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100597 jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);
598
599 if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) {
600 u32 ret = readl(reg + CAST_STATUS12);
601
602 dev_err(dev, "Encoder/decoder error, status=0x%08x", ret);
603 mxc_jpeg_sw_reset(reg);
604 buf_state = VB2_BUF_STATE_ERROR;
605 goto buffers_done;
606 }
607
608 if (!(dec_ret & SLOT_STATUS_FRMDONE))
609 goto job_unlock;
610
611 if (jpeg->mode == MXC_JPEG_ENCODE &&
612 ctx->enc_state == MXC_JPEG_ENC_CONF) {
613 ctx->enc_state = MXC_JPEG_ENCODING;
614 dev_dbg(dev, "Encoder config finished. Start encoding...\n");
615 mxc_jpeg_enc_mode_go(dev, reg);
616 goto job_unlock;
617 }
618 if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed) {
619 jpeg_src_buf->dht_needed = false;
620 dev_dbg(dev, "Decoder DHT cfg finished. Start decoding...\n");
621 goto job_unlock;
622 }
623 if (jpeg->mode == MXC_JPEG_ENCODE) {
624 payload = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR));
625 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
626 dev_dbg(dev, "Encoding finished, payload size: %ld\n",
627 payload);
628 } else {
629 q_data = mxc_jpeg_get_q_data(ctx, cap_type);
630 payload = q_data->sizeimage[0];
631 vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
632 vb2_set_plane_payload(&dst_buf->vb2_buf, 1, 0);
633 if (q_data->fmt->colplanes == 2) {
634 payload = q_data->sizeimage[1];
635 vb2_set_plane_payload(&dst_buf->vb2_buf, 1, payload);
636 }
637 dev_dbg(dev, "Decoding finished, payload size: %ld + %ld\n",
638 vb2_get_plane_payload(&dst_buf->vb2_buf, 0),
639 vb2_get_plane_payload(&dst_buf->vb2_buf, 1));
640 }
641
642 /* short preview of the results */
643 dev_dbg(dev, "src_buf preview: ");
644 print_mxc_buf(jpeg, &src_buf->vb2_buf, 32);
645 dev_dbg(dev, "dst_buf preview: ");
646 print_mxc_buf(jpeg, &dst_buf->vb2_buf, 32);
647 buf_state = VB2_BUF_STATE_DONE;
648
649buffers_done:
650 jpeg->slot_data[slot].used = false; /* unused, but don't free */
651 v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
652 v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
653 v4l2_m2m_buf_done(src_buf, buf_state);
654 v4l2_m2m_buf_done(dst_buf, buf_state);
655 spin_unlock(&jpeg->hw_lock);
656 v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
657 return IRQ_HANDLED;
658job_unlock:
659 spin_unlock(&jpeg->hw_lock);
660 return IRQ_HANDLED;
661}
662
663static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,
664 u32 fourcc,
665 u16 w, u16 h)
666{
667 int sof_length;
668
669 sof->precision = 8; /* TODO allow 8/12 bit precision*/
670 sof->height = h;
671 _bswap16(&sof->height);
672 sof->width = w;
673 _bswap16(&sof->width);
674
675 switch (fourcc) {
676 case V4L2_PIX_FMT_NV12:
677 sof->components_no = 3;
678 sof->comp[0].v = 0x2;
679 sof->comp[0].h = 0x2;
680 break;
681 case V4L2_PIX_FMT_YUYV:
682 sof->components_no = 3;
683 sof->comp[0].v = 0x1;
684 sof->comp[0].h = 0x2;
685 break;
686 case V4L2_PIX_FMT_YUV24:
687 case V4L2_PIX_FMT_RGB24:
688 default:
689 sof->components_no = 3;
690 break;
691 case V4L2_PIX_FMT_ARGB32:
692 sof->components_no = 4;
693 break;
694 case V4L2_PIX_FMT_GREY:
695 sof->components_no = 1;
696 break;
697 }
698 sof_length = 8 + 3 * sof->components_no;
699 sof->length = sof_length;
700 _bswap16(&sof->length);
701
702 return sof_length; /* not swaped */
703}
704
705static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos,
706 u32 fourcc)
707{
708 int sos_length;
709 u8 *sof_u8 = (u8 *)sos;
710
711 switch (fourcc) {
712 case V4L2_PIX_FMT_NV12:
713 sos->components_no = 3;
714 break;
715 case V4L2_PIX_FMT_YUYV:
716 sos->components_no = 3;
717 break;
718 case V4L2_PIX_FMT_YUV24:
719 case V4L2_PIX_FMT_RGB24:
720 default:
721 sos->components_no = 3;
722 break;
723 case V4L2_PIX_FMT_ARGB32:
724 sos->components_no = 4;
725 break;
726 case V4L2_PIX_FMT_GREY:
727 sos->components_no = 1;
728 break;
729 }
730 sos_length = 6 + 2 * sos->components_no;
731 sos->length = sos_length;
732 _bswap16(&sos->length);
733
734 /* SOS ignorable bytes, not so ignorable after all */
735 sof_u8[sos_length - 1] = 0x0;
736 sof_u8[sos_length - 2] = 0x3f;
737 sof_u8[sos_length - 3] = 0x0;
738
739 return sos_length; /* not swaped */
740}
741
742static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
743 u32 fourcc,
744 u16 w, u16 h)
745{
746 unsigned int offset = 0;
747 u8 *cfg = (u8 *)cfg_stream_vaddr;
748 struct mxc_jpeg_sof *sof;
749 struct mxc_jpeg_sos *sos;
750
751 memcpy(cfg + offset, jpeg_soi, ARRAY_SIZE(jpeg_soi));
752 offset += ARRAY_SIZE(jpeg_soi);
753
754 if (fourcc == V4L2_PIX_FMT_RGB24 ||
755 fourcc == V4L2_PIX_FMT_ARGB32) {
756 memcpy(cfg + offset, jpeg_app14, sizeof(jpeg_app14));
757 offset += sizeof(jpeg_app14);
758 } else {
759 memcpy(cfg + offset, jpeg_app0, sizeof(jpeg_app0));
760 offset += sizeof(jpeg_app0);
761 }
762
763 memcpy(cfg + offset, jpeg_dqt, sizeof(jpeg_dqt));
764 offset += sizeof(jpeg_dqt);
765
766 memcpy(cfg + offset, jpeg_sof_maximal, sizeof(jpeg_sof_maximal));
767 offset += 2; /* skip marker ID */
768 sof = (struct mxc_jpeg_sof *)(cfg + offset);
769 offset += mxc_jpeg_fixup_sof(sof, fourcc, w, h);
770
771 memcpy(cfg + offset, jpeg_dht, sizeof(jpeg_dht));
772 offset += sizeof(jpeg_dht);
773
774 memcpy(cfg + offset, jpeg_dri, sizeof(jpeg_dri));
775 offset += sizeof(jpeg_dri);
776
777 memcpy(cfg + offset, jpeg_sos_maximal, sizeof(jpeg_sos_maximal));
778 offset += 2; /* skip marker ID */
779 sos = (struct mxc_jpeg_sos *)(cfg + offset);
780 offset += mxc_jpeg_fixup_sos(sos, fourcc);
781
Mirela Rabulea34acaf62021-09-27 20:56:57 +0200782 memcpy(cfg + offset, jpeg_image_red, sizeof(jpeg_image_red));
783 offset += sizeof(jpeg_image_red);
784
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100785 memcpy(cfg + offset, jpeg_eoi, sizeof(jpeg_eoi));
786 offset += sizeof(jpeg_eoi);
787
788 return offset;
789}
790
791static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
792 struct mxc_jpeg_ctx *ctx,
793 struct vb2_buffer *src_buf,
794 struct vb2_buffer *dst_buf)
795{
796 enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
797 struct mxc_jpeg_q_data *q_data_cap;
798 enum mxc_jpeg_image_format img_fmt;
799 struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
800 void __iomem *reg = jpeg->base_reg;
801 unsigned int slot = ctx->slot;
802 struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
803 struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
804 dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
805 dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
806 dma_addr_t cfg_stream_handle = jpeg->slot_data[slot].cfg_stream_handle;
807 unsigned int *cfg_size = &jpeg->slot_data[slot].cfg_stream_size;
808 void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
809 struct mxc_jpeg_src_buf *jpeg_src_buf;
810
811 jpeg_src_buf = vb2_to_mxc_buf(src_buf);
812
813 /* setup the decoding descriptor */
814 desc->next_descpt_ptr = 0; /* end of chain */
815 q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
816 desc->imgsize = q_data_cap->w_adjusted << 16 | q_data_cap->h_adjusted;
817 img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data_cap->fmt->fourcc);
818 desc->stm_ctrl &= ~STM_CTRL_IMAGE_FORMAT(0xF); /* clear image format */
819 desc->stm_ctrl |= STM_CTRL_IMAGE_FORMAT(img_fmt);
Mirela Rabuleaae3cab72021-09-27 20:57:19 +0200820 desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100821 desc->line_pitch = q_data_cap->bytesperline[0];
822 mxc_jpeg_addrs(desc, dst_buf, src_buf, 0);
823 mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(src_buf, 0), 1024));
824 print_descriptor_info(jpeg->dev, desc);
825
826 if (!jpeg_src_buf->dht_needed) {
827 /* validate the decoding descriptor */
828 mxc_jpeg_set_desc(desc_handle, reg, slot);
829 return;
830 }
831
832 /*
833 * if a default huffman table is needed, use the config descriptor to
834 * inject a DHT, by chaining it before the decoding descriptor
835 */
836 *cfg_size = mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
837 V4L2_PIX_FMT_YUYV,
838 MXC_JPEG_MIN_WIDTH,
839 MXC_JPEG_MIN_HEIGHT);
840 cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
841 cfg_desc->buf_base0 = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
842 cfg_desc->buf_base1 = 0;
843 cfg_desc->imgsize = MXC_JPEG_MIN_WIDTH << 16;
844 cfg_desc->imgsize |= MXC_JPEG_MIN_HEIGHT;
845 cfg_desc->line_pitch = MXC_JPEG_MIN_WIDTH * 2;
846 cfg_desc->stm_ctrl = STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV422);
Mirela Rabuleaae3cab72021-09-27 20:57:19 +0200847 cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100848 cfg_desc->stm_bufbase = cfg_stream_handle;
849 cfg_desc->stm_bufsize = ALIGN(*cfg_size, 1024);
850 print_descriptor_info(jpeg->dev, cfg_desc);
851
852 /* validate the configuration descriptor */
853 mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
854}
855
856static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
857 struct mxc_jpeg_ctx *ctx,
858 struct vb2_buffer *src_buf,
859 struct vb2_buffer *dst_buf)
860{
861 struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
862 void __iomem *reg = jpeg->base_reg;
863 unsigned int slot = ctx->slot;
864 struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
865 struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
866 dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
867 dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
868 void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
869 struct mxc_jpeg_q_data *q_data;
870 enum mxc_jpeg_image_format img_fmt;
871 int w, h;
872
873 q_data = mxc_jpeg_get_q_data(ctx, src_buf->vb2_queue->type);
874
875 jpeg->slot_data[slot].cfg_stream_size =
876 mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
877 q_data->fmt->fourcc,
878 q_data->w_adjusted,
879 q_data->h_adjusted);
880
881 /* chain the config descriptor with the encoding descriptor */
882 cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
883
884 cfg_desc->buf_base0 = jpeg->slot_data[slot].cfg_stream_handle;
885 cfg_desc->buf_base1 = 0;
886 cfg_desc->line_pitch = 0;
887 cfg_desc->stm_bufbase = 0; /* no output expected */
888 cfg_desc->stm_bufsize = 0x0;
889 cfg_desc->imgsize = 0;
890 cfg_desc->stm_ctrl = STM_CTRL_CONFIG_MOD(1);
Mirela Rabuleaae3cab72021-09-27 20:57:19 +0200891 cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100892
893 desc->next_descpt_ptr = 0; /* end of chain */
894
895 /* use adjusted resolution for CAST IP job */
896 w = q_data->w_adjusted;
897 h = q_data->h_adjusted;
898 mxc_jpeg_set_res(desc, w, h);
899 mxc_jpeg_set_line_pitch(desc, w * (q_data->fmt->depth / 8));
900 mxc_jpeg_set_bufsize(desc, desc->line_pitch * h);
901 img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data->fmt->fourcc);
902 if (img_fmt == MXC_JPEG_INVALID)
903 dev_err(jpeg->dev, "No valid image format detected\n");
904 desc->stm_ctrl = STM_CTRL_CONFIG_MOD(0) |
905 STM_CTRL_IMAGE_FORMAT(img_fmt);
Mirela Rabuleaae3cab72021-09-27 20:57:19 +0200906 desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100907 mxc_jpeg_addrs(desc, src_buf, dst_buf, 0);
908 dev_dbg(jpeg->dev, "cfg_desc:\n");
909 print_descriptor_info(jpeg->dev, cfg_desc);
910 dev_dbg(jpeg->dev, "enc desc:\n");
911 print_descriptor_info(jpeg->dev, desc);
912 print_wrapper_info(jpeg->dev, reg);
913 print_cast_status(jpeg->dev, reg, MXC_JPEG_ENCODE);
914
915 /* validate the configuration descriptor */
916 mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
917}
918
919static void mxc_jpeg_device_run(void *priv)
920{
921 struct mxc_jpeg_ctx *ctx = priv;
922 struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
923 void __iomem *reg = jpeg->base_reg;
924 struct device *dev = jpeg->dev;
925 struct vb2_v4l2_buffer *src_buf, *dst_buf;
926 unsigned long flags;
927 struct mxc_jpeg_q_data *q_data_cap, *q_data_out;
928 struct mxc_jpeg_src_buf *jpeg_src_buf;
929
930 spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
931 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
932 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
933 if (!src_buf || !dst_buf) {
934 dev_err(dev, "Null src or dst buf\n");
935 goto end;
936 }
937
938 q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
939 if (!q_data_cap)
940 goto end;
941 q_data_out = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
942 if (!q_data_out)
943 goto end;
944 src_buf->sequence = q_data_out->sequence++;
945 dst_buf->sequence = q_data_cap->sequence++;
946
947 v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
948
949 jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);
950 if (jpeg_src_buf->jpeg_parse_error) {
951 jpeg->slot_data[ctx->slot].used = false;
952 v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
953 v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
954 v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
955 v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
956 spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
957 v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
958
959 return;
960 }
961
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100962 mxc_jpeg_enable(reg);
963 mxc_jpeg_set_l_endian(reg, 1);
964
965 ctx->slot = mxc_get_free_slot(jpeg->slot_data, MXC_MAX_SLOTS);
966 if (ctx->slot >= MXC_MAX_SLOTS) {
967 dev_err(dev, "No more free slots\n");
968 goto end;
969 }
970 if (!mxc_jpeg_alloc_slot_data(jpeg, ctx->slot)) {
Colin Ian King033fc892021-03-23 10:21:41 +0100971 dev_err(dev, "Cannot allocate slot data\n");
Mirela Rabulea2db16c62021-03-11 09:53:17 +0100972 goto end;
973 }
974
975 mxc_jpeg_enable_slot(reg, ctx->slot);
976 mxc_jpeg_enable_irq(reg, ctx->slot);
977
978 if (jpeg->mode == MXC_JPEG_ENCODE) {
979 dev_dbg(dev, "Encoding on slot %d\n", ctx->slot);
980 ctx->enc_state = MXC_JPEG_ENC_CONF;
981 mxc_jpeg_config_enc_desc(&dst_buf->vb2_buf, ctx,
982 &src_buf->vb2_buf, &dst_buf->vb2_buf);
983 mxc_jpeg_enc_mode_conf(dev, reg); /* start config phase */
984 } else {
985 dev_dbg(dev, "Decoding on slot %d\n", ctx->slot);
986 print_mxc_buf(jpeg, &src_buf->vb2_buf, 0);
987 mxc_jpeg_config_dec_desc(&dst_buf->vb2_buf, ctx,
988 &src_buf->vb2_buf, &dst_buf->vb2_buf);
989 mxc_jpeg_dec_mode_go(dev, reg);
990 }
991end:
992 spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
993}
994
995static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
996 struct v4l2_decoder_cmd *cmd)
997{
998 struct v4l2_fh *fh = file->private_data;
999 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
1000 struct device *dev = ctx->mxc_jpeg->dev;
1001 int ret;
1002
1003 ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);
1004 if (ret < 0)
1005 return ret;
1006
1007 if (cmd->cmd == V4L2_DEC_CMD_STOP) {
1008 dev_dbg(dev, "Received V4L2_DEC_CMD_STOP");
1009 if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) {
1010 /* No more src bufs, notify app EOS */
1011 notify_eos(ctx);
1012 } else {
1013 /* will send EOS later*/
1014 ctx->stopping = 1;
1015 }
1016 }
1017
1018 return 0;
1019}
1020
1021static int mxc_jpeg_encoder_cmd(struct file *file, void *priv,
1022 struct v4l2_encoder_cmd *cmd)
1023{
1024 struct v4l2_fh *fh = file->private_data;
1025 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
1026 struct device *dev = ctx->mxc_jpeg->dev;
1027 int ret;
1028
1029 ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd);
1030 if (ret < 0)
1031 return ret;
1032
1033 if (cmd->cmd == V4L2_ENC_CMD_STOP) {
1034 dev_dbg(dev, "Received V4L2_ENC_CMD_STOP");
1035 if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) {
1036 /* No more src bufs, notify app EOS */
1037 notify_eos(ctx);
1038 } else {
1039 /* will send EOS later*/
1040 ctx->stopping = 1;
1041 }
1042 }
1043
1044 return 0;
1045}
1046
1047static int mxc_jpeg_queue_setup(struct vb2_queue *q,
1048 unsigned int *nbuffers,
1049 unsigned int *nplanes,
1050 unsigned int sizes[],
1051 struct device *alloc_ctxs[])
1052{
1053 struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
1054 struct mxc_jpeg_q_data *q_data = NULL;
1055 int i;
1056
1057 q_data = mxc_jpeg_get_q_data(ctx, q->type);
1058 if (!q_data)
1059 return -EINVAL;
1060
1061 /* Handle CREATE_BUFS situation - *nplanes != 0 */
1062 if (*nplanes) {
1063 for (i = 0; i < *nplanes; i++) {
1064 if (sizes[i] < q_data->sizeimage[i])
1065 return -EINVAL;
1066 }
1067 return 0;
1068 }
1069
1070 /* Handle REQBUFS situation */
1071 *nplanes = q_data->fmt->colplanes;
1072 for (i = 0; i < *nplanes; i++)
1073 sizes[i] = q_data->sizeimage[i];
1074
1075 return 0;
1076}
1077
1078static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
1079{
1080 struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
1081 struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type);
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01001082 int ret;
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001083
1084 dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
1085 q_data->sequence = 0;
1086
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01001087 ret = pm_runtime_resume_and_get(ctx->mxc_jpeg->dev);
1088 if (ret < 0) {
1089 dev_err(ctx->mxc_jpeg->dev, "Failed to power up jpeg\n");
1090 return ret;
1091 }
1092
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001093 return 0;
1094}
1095
1096static void mxc_jpeg_stop_streaming(struct vb2_queue *q)
1097{
1098 struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
1099 struct vb2_v4l2_buffer *vbuf;
1100
1101 dev_dbg(ctx->mxc_jpeg->dev, "Stop streaming ctx=%p", ctx);
1102
1103 /* Release all active buffers */
1104 for (;;) {
1105 if (V4L2_TYPE_IS_OUTPUT(q->type))
1106 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
1107 else
1108 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
1109 if (!vbuf)
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01001110 break;
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001111 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
1112 }
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01001113 pm_runtime_put_sync(&ctx->mxc_jpeg->pdev->dev);
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001114}
1115
1116static int mxc_jpeg_valid_comp_id(struct device *dev,
1117 struct mxc_jpeg_sof *sof,
1118 struct mxc_jpeg_sos *sos)
1119{
1120 int valid = 1;
1121 int i;
1122
1123 /*
1124 * there's a limitation in the IP that the component IDs must be
1125 * between 0..4, if they are not, let's patch them
1126 */
1127 for (i = 0; i < sof->components_no; i++)
1128 if (sof->comp[i].id > MXC_JPEG_MAX_COMPONENTS) {
1129 valid = 0;
1130 dev_err(dev, "Component %d has invalid ID: %d",
1131 i, sof->comp[i].id);
1132 }
1133 if (!valid)
1134 /* patch all comp IDs if at least one is invalid */
1135 for (i = 0; i < sof->components_no; i++) {
1136 dev_warn(dev, "Component %d ID patched to: %d",
1137 i, i + 1);
1138 sof->comp[i].id = i + 1;
1139 sos->comp[i].id = i + 1;
1140 }
1141
1142 return valid;
1143}
1144
1145static u32 mxc_jpeg_get_image_format(struct device *dev,
Colin Ian King5dccfce2021-03-23 15:24:21 +01001146 const struct v4l2_jpeg_header *header)
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001147{
1148 int i;
1149 u32 fourcc = 0;
1150
1151 for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++)
Colin Ian King5dccfce2021-03-23 15:24:21 +01001152 if (mxc_formats[i].subsampling == header->frame.subsampling &&
1153 mxc_formats[i].nc == header->frame.num_components) {
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001154 fourcc = mxc_formats[i].fourcc;
1155 break;
1156 }
1157 if (fourcc == 0) {
1158 dev_err(dev, "Could not identify image format nc=%d, subsampling=%d\n",
Colin Ian King5dccfce2021-03-23 15:24:21 +01001159 header->frame.num_components,
1160 header->frame.subsampling);
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001161 return fourcc;
1162 }
1163 /*
1164 * If the transform flag from APP14 marker is 0, images that are
1165 * encoded with 3 components have RGB colorspace, see Recommendation
1166 * ITU-T T.872 chapter 6.5.3 APP14 marker segment for colour encoding
1167 */
1168 if (fourcc == V4L2_PIX_FMT_YUV24 || fourcc == V4L2_PIX_FMT_RGB24) {
Colin Ian King5dccfce2021-03-23 15:24:21 +01001169 if (header->app14_tf == V4L2_JPEG_APP14_TF_CMYK_RGB)
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001170 fourcc = V4L2_PIX_FMT_RGB24;
1171 else
1172 fourcc = V4L2_PIX_FMT_YUV24;
1173 }
1174
1175 return fourcc;
1176}
1177
1178static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q,
1179 u32 precision)
1180{
1181 /* Bytes distance between the leftmost pixels in two adjacent lines */
1182 if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
1183 /* bytesperline unused for compressed formats */
1184 q->bytesperline[0] = 0;
1185 q->bytesperline[1] = 0;
1186 } else if (q->fmt->fourcc == V4L2_PIX_FMT_NV12) {
1187 /* When the image format is planar the bytesperline value
1188 * applies to the first plane and is divided by the same factor
1189 * as the width field for the other planes
1190 */
1191 q->bytesperline[0] = q->w * (precision / 8) *
1192 (q->fmt->depth / 8);
1193 q->bytesperline[1] = q->bytesperline[0];
1194 } else {
1195 /* single plane formats */
1196 q->bytesperline[0] = q->w * (precision / 8) *
1197 (q->fmt->depth / 8);
1198 q->bytesperline[1] = 0;
1199 }
1200}
1201
1202static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
1203{
1204 if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
1205 /* if no sizeimage from user, assume worst jpeg compression */
1206 if (!q->sizeimage[0])
1207 q->sizeimage[0] = 6 * q->w * q->h;
1208 q->sizeimage[1] = 0;
1209
1210 if (q->sizeimage[0] > MXC_JPEG_MAX_SIZEIMAGE)
1211 q->sizeimage[0] = MXC_JPEG_MAX_SIZEIMAGE;
1212
1213 /* jpeg stream size must be multiple of 1K */
1214 q->sizeimage[0] = ALIGN(q->sizeimage[0], 1024);
1215 } else {
1216 q->sizeimage[0] = q->bytesperline[0] * q->h;
1217 q->sizeimage[1] = 0;
1218 if (q->fmt->fourcc == V4L2_PIX_FMT_NV12)
1219 q->sizeimage[1] = q->sizeimage[0] / 2;
1220 }
1221}
1222
1223static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
1224 u8 *src_addr, u32 size, bool *dht_needed)
1225{
1226 struct device *dev = ctx->mxc_jpeg->dev;
1227 struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
1228 enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1229 bool src_chg = false;
1230 u32 fourcc;
1231 struct v4l2_jpeg_header header;
1232 struct mxc_jpeg_sof *psof = NULL;
1233 struct mxc_jpeg_sos *psos = NULL;
1234 int ret;
1235
1236 memset(&header, 0, sizeof(header));
1237 ret = v4l2_jpeg_parse_header((void *)src_addr, size, &header);
1238 if (ret < 0) {
1239 dev_err(dev, "Error parsing JPEG stream markers\n");
1240 return ret;
1241 }
1242
1243 /* if DHT marker present, no need to inject default one */
1244 *dht_needed = (header.num_dht == 0);
1245
1246 q_data_out = mxc_jpeg_get_q_data(ctx,
1247 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
1248 if (q_data_out->w == 0 && q_data_out->h == 0) {
1249 dev_warn(dev, "Invalid user resolution 0x0");
1250 dev_warn(dev, "Keeping resolution from JPEG: %dx%d",
1251 header.frame.width, header.frame.height);
1252 q_data_out->w = header.frame.width;
1253 q_data_out->h = header.frame.height;
1254 } else if (header.frame.width != q_data_out->w ||
1255 header.frame.height != q_data_out->h) {
1256 dev_err(dev,
1257 "Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)",
1258 header.frame.width, header.frame.height,
1259 q_data_out->w, q_data_out->h);
1260 return -EINVAL;
1261 }
1262 if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) {
1263 dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n",
1264 header.frame.width, header.frame.height);
1265 return -EINVAL;
1266 }
1267 if (header.frame.width > MXC_JPEG_MAX_WIDTH ||
1268 header.frame.height > MXC_JPEG_MAX_HEIGHT) {
1269 dev_err(dev, "JPEG width or height should be <= 8192: %dx%d\n",
1270 header.frame.width, header.frame.height);
1271 return -EINVAL;
1272 }
1273 if (header.frame.width < MXC_JPEG_MIN_WIDTH ||
1274 header.frame.height < MXC_JPEG_MIN_HEIGHT) {
1275 dev_err(dev, "JPEG width or height should be > 64: %dx%d\n",
1276 header.frame.width, header.frame.height);
1277 return -EINVAL;
1278 }
1279 if (header.frame.num_components > V4L2_JPEG_MAX_COMPONENTS) {
1280 dev_err(dev, "JPEG number of components should be <=%d",
1281 V4L2_JPEG_MAX_COMPONENTS);
1282 return -EINVAL;
1283 }
1284 /* check and, if necessary, patch component IDs*/
1285 psof = (struct mxc_jpeg_sof *)header.sof.start;
1286 psos = (struct mxc_jpeg_sos *)header.sos.start;
1287 if (!mxc_jpeg_valid_comp_id(dev, psof, psos))
1288 dev_warn(dev, "JPEG component ids should be 0-3 or 1-4");
1289
Colin Ian King5dccfce2021-03-23 15:24:21 +01001290 fourcc = mxc_jpeg_get_image_format(dev, &header);
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001291 if (fourcc == 0)
1292 return -EINVAL;
1293
1294 /*
1295 * set-up the capture queue with the pixelformat and resolution
1296 * detected from the jpeg output stream
1297 */
1298 q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
1299 if (q_data_cap->w != header.frame.width ||
1300 q_data_cap->h != header.frame.height)
1301 src_chg = true;
1302 q_data_cap->w = header.frame.width;
1303 q_data_cap->h = header.frame.height;
1304 q_data_cap->fmt = mxc_jpeg_find_format(ctx, fourcc);
1305 q_data_cap->w_adjusted = q_data_cap->w;
1306 q_data_cap->h_adjusted = q_data_cap->h;
1307 /*
1308 * align up the resolution for CAST IP,
1309 * but leave the buffer resolution unchanged
1310 */
1311 v4l_bound_align_image(&q_data_cap->w_adjusted,
1312 q_data_cap->w_adjusted, /* adjust up */
1313 MXC_JPEG_MAX_WIDTH,
1314 q_data_cap->fmt->h_align,
1315 &q_data_cap->h_adjusted,
1316 q_data_cap->h_adjusted, /* adjust up */
1317 MXC_JPEG_MAX_HEIGHT,
1318 q_data_cap->fmt->v_align,
1319 0);
1320 dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
1321 q_data_cap->w, q_data_cap->h,
1322 q_data_cap->w_adjusted, q_data_cap->h_adjusted,
1323 (fourcc & 0xff),
1324 (fourcc >> 8) & 0xff,
1325 (fourcc >> 16) & 0xff,
1326 (fourcc >> 24) & 0xff);
1327
1328 /* setup bytesperline/sizeimage for capture queue */
1329 mxc_jpeg_bytesperline(q_data_cap, header.frame.precision);
1330 mxc_jpeg_sizeimage(q_data_cap);
1331
1332 /*
1333 * if the CAPTURE format was updated with new values, regardless of
1334 * whether they match the values set by the client or not, signal
1335 * a source change event
1336 */
1337 if (src_chg)
1338 notify_src_chg(ctx);
1339
1340 return 0;
1341}
1342
1343static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
1344{
1345 int ret;
1346 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1347 struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1348 struct mxc_jpeg_src_buf *jpeg_src_buf;
1349
1350 if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1351 goto end;
1352
1353 /* for V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE */
1354 if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
1355 goto end;
1356
1357 jpeg_src_buf = vb2_to_mxc_buf(vb);
1358 jpeg_src_buf->jpeg_parse_error = false;
1359 ret = mxc_jpeg_parse(ctx,
1360 (u8 *)vb2_plane_vaddr(vb, 0),
1361 vb2_get_plane_payload(vb, 0),
1362 &jpeg_src_buf->dht_needed);
1363 if (ret)
1364 jpeg_src_buf->jpeg_parse_error = true;
1365
1366end:
1367 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1368}
1369
1370static int mxc_jpeg_buf_out_validate(struct vb2_buffer *vb)
1371{
1372 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1373
1374 vbuf->field = V4L2_FIELD_NONE;
1375
1376 return 0;
1377}
1378
1379static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb)
1380{
1381 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1382 struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1383 struct mxc_jpeg_q_data *q_data = NULL;
1384 struct device *dev = ctx->mxc_jpeg->dev;
1385 unsigned long sizeimage;
1386 int i;
1387
1388 vbuf->field = V4L2_FIELD_NONE;
1389
1390 q_data = mxc_jpeg_get_q_data(ctx, vb->vb2_queue->type);
1391 if (!q_data)
1392 return -EINVAL;
1393 for (i = 0; i < q_data->fmt->colplanes; i++) {
1394 sizeimage = q_data->sizeimage[i];
1395 if (vb2_plane_size(vb, i) < sizeimage) {
1396 dev_err(dev, "plane %d too small (%lu < %lu)",
1397 i, vb2_plane_size(vb, i), sizeimage);
1398 return -EINVAL;
1399 }
1400 vb2_set_plane_payload(vb, i, sizeimage);
1401 }
1402 return 0;
1403}
1404
1405static const struct vb2_ops mxc_jpeg_qops = {
1406 .queue_setup = mxc_jpeg_queue_setup,
1407 .wait_prepare = vb2_ops_wait_prepare,
1408 .wait_finish = vb2_ops_wait_finish,
1409 .buf_out_validate = mxc_jpeg_buf_out_validate,
1410 .buf_prepare = mxc_jpeg_buf_prepare,
1411 .start_streaming = mxc_jpeg_start_streaming,
1412 .stop_streaming = mxc_jpeg_stop_streaming,
1413 .buf_queue = mxc_jpeg_buf_queue,
1414};
1415
1416static int mxc_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
1417 struct vb2_queue *dst_vq)
1418{
1419 struct mxc_jpeg_ctx *ctx = priv;
1420 int ret;
1421
1422 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1423 src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
1424 src_vq->drv_priv = ctx;
1425 src_vq->buf_struct_size = sizeof(struct mxc_jpeg_src_buf);
1426 src_vq->ops = &mxc_jpeg_qops;
1427 src_vq->mem_ops = &vb2_dma_contig_memops;
1428 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1429 src_vq->lock = &ctx->mxc_jpeg->lock;
1430 src_vq->dev = ctx->mxc_jpeg->dev;
1431 src_vq->allow_zero_bytesused = 1; /* keep old userspace apps working */
1432
1433 ret = vb2_queue_init(src_vq);
1434 if (ret)
1435 return ret;
1436
1437 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1438 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
1439 dst_vq->drv_priv = ctx;
1440 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1441 dst_vq->ops = &mxc_jpeg_qops;
1442 dst_vq->mem_ops = &vb2_dma_contig_memops;
1443 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1444 dst_vq->lock = &ctx->mxc_jpeg->lock;
1445 dst_vq->dev = ctx->mxc_jpeg->dev;
1446
1447 ret = vb2_queue_init(dst_vq);
1448 return ret;
1449}
1450
1451static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx)
1452{
1453 struct mxc_jpeg_q_data *out_q = &ctx->out_q;
1454 struct mxc_jpeg_q_data *cap_q = &ctx->cap_q;
1455 struct mxc_jpeg_q_data *q[2] = {out_q, cap_q};
1456 int i;
1457
1458 if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {
1459 out_q->fmt = mxc_jpeg_find_format(ctx, MXC_JPEG_DEFAULT_PFMT);
1460 cap_q->fmt = mxc_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG);
1461 } else {
1462 out_q->fmt = mxc_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG);
1463 cap_q->fmt = mxc_jpeg_find_format(ctx, MXC_JPEG_DEFAULT_PFMT);
1464 }
1465
1466 for (i = 0; i < 2; i++) {
1467 q[i]->w = MXC_JPEG_DEFAULT_WIDTH;
1468 q[i]->h = MXC_JPEG_DEFAULT_HEIGHT;
1469 q[i]->w_adjusted = MXC_JPEG_DEFAULT_WIDTH;
1470 q[i]->h_adjusted = MXC_JPEG_DEFAULT_HEIGHT;
1471 mxc_jpeg_bytesperline(q[i], 8);
1472 mxc_jpeg_sizeimage(q[i]);
1473 }
1474}
1475
1476static int mxc_jpeg_open(struct file *file)
1477{
1478 struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
1479 struct video_device *mxc_vfd = video_devdata(file);
1480 struct device *dev = mxc_jpeg->dev;
1481 struct mxc_jpeg_ctx *ctx;
1482 int ret = 0;
1483
1484 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1485 if (!ctx)
1486 return -ENOMEM;
1487
1488 if (mutex_lock_interruptible(&mxc_jpeg->lock)) {
1489 ret = -ERESTARTSYS;
1490 goto free;
1491 }
1492
1493 v4l2_fh_init(&ctx->fh, mxc_vfd);
1494 file->private_data = &ctx->fh;
1495 v4l2_fh_add(&ctx->fh);
1496
1497 ctx->mxc_jpeg = mxc_jpeg;
1498
1499 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(mxc_jpeg->m2m_dev, ctx,
1500 mxc_jpeg_queue_init);
1501
1502 if (IS_ERR(ctx->fh.m2m_ctx)) {
1503 ret = PTR_ERR(ctx->fh.m2m_ctx);
1504 goto error;
1505 }
1506
1507 mxc_jpeg_set_default_params(ctx);
1508 ctx->slot = MXC_MAX_SLOTS; /* slot not allocated yet */
1509
1510 if (mxc_jpeg->mode == MXC_JPEG_DECODE)
1511 dev_dbg(dev, "Opened JPEG decoder instance %p\n", ctx);
1512 else
1513 dev_dbg(dev, "Opened JPEG encoder instance %p\n", ctx);
1514 mutex_unlock(&mxc_jpeg->lock);
1515
1516 return 0;
1517
1518error:
1519 v4l2_fh_del(&ctx->fh);
1520 v4l2_fh_exit(&ctx->fh);
1521 mutex_unlock(&mxc_jpeg->lock);
1522free:
1523 kfree(ctx);
1524 return ret;
1525}
1526
1527static int mxc_jpeg_querycap(struct file *file, void *priv,
1528 struct v4l2_capability *cap)
1529{
1530 struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
1531
1532 strscpy(cap->driver, MXC_JPEG_NAME " codec", sizeof(cap->driver));
1533 strscpy(cap->card, MXC_JPEG_NAME " codec", sizeof(cap->card));
1534 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
1535 dev_name(mxc_jpeg->dev));
1536 cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
1537 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1538
1539 return 0;
1540}
1541
1542static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
1543 struct v4l2_fmtdesc *f)
1544{
1545 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
1546
1547 if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)
1548 return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
1549 MXC_JPEG_FMT_TYPE_ENC);
1550 else
1551 return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
1552 MXC_JPEG_FMT_TYPE_RAW);
1553}
1554
1555static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
1556 struct v4l2_fmtdesc *f)
1557{
1558 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
1559
1560 if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
1561 return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
1562 MXC_JPEG_FMT_TYPE_ENC);
1563 else
1564 return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
1565 MXC_JPEG_FMT_TYPE_RAW);
1566}
1567
Rikard Falkeborn7ec1c4a2021-06-12 01:42:01 +02001568static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fmt,
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001569 struct mxc_jpeg_ctx *ctx, int q_type)
1570{
1571 struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
1572 struct v4l2_plane_pix_format *pfmt;
1573 u32 w = (pix_mp->width < MXC_JPEG_MAX_WIDTH) ?
1574 pix_mp->width : MXC_JPEG_MAX_WIDTH;
1575 u32 h = (pix_mp->height < MXC_JPEG_MAX_HEIGHT) ?
1576 pix_mp->height : MXC_JPEG_MAX_HEIGHT;
1577 int i;
1578 struct mxc_jpeg_q_data tmp_q;
1579
1580 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
1581 pix_mp->field = V4L2_FIELD_NONE;
1582 pix_mp->num_planes = fmt->colplanes;
1583 pix_mp->pixelformat = fmt->fourcc;
1584
1585 /*
1586 * use MXC_JPEG_H_ALIGN instead of fmt->v_align, for vertical
1587 * alignment, to loosen up the alignment to multiple of 8,
1588 * otherwise NV12-1080p fails as 1080 is not a multiple of 16
1589 */
1590 v4l_bound_align_image(&w,
1591 MXC_JPEG_MIN_WIDTH,
1592 w, /* adjust downwards*/
1593 fmt->h_align,
1594 &h,
1595 MXC_JPEG_MIN_HEIGHT,
1596 h, /* adjust downwards*/
1597 MXC_JPEG_H_ALIGN,
1598 0);
1599 pix_mp->width = w; /* negotiate the width */
1600 pix_mp->height = h; /* negotiate the height */
1601
1602 /* get user input into the tmp_q */
1603 tmp_q.w = w;
1604 tmp_q.h = h;
1605 tmp_q.fmt = fmt;
1606 for (i = 0; i < pix_mp->num_planes; i++) {
1607 pfmt = &pix_mp->plane_fmt[i];
1608 tmp_q.bytesperline[i] = pfmt->bytesperline;
1609 tmp_q.sizeimage[i] = pfmt->sizeimage;
1610 }
1611
1612 /* calculate bytesperline & sizeimage into the tmp_q */
1613 mxc_jpeg_bytesperline(&tmp_q, 8);
1614 mxc_jpeg_sizeimage(&tmp_q);
1615
1616 /* adjust user format according to our calculations */
1617 for (i = 0; i < pix_mp->num_planes; i++) {
1618 pfmt = &pix_mp->plane_fmt[i];
1619 memset(pfmt->reserved, 0, sizeof(pfmt->reserved));
1620 pfmt->bytesperline = tmp_q.bytesperline[i];
1621 pfmt->sizeimage = tmp_q.sizeimage[i];
1622 }
1623
1624 /* fix colorspace information to sRGB for both output & capture */
1625 pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
1626 pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601;
1627 pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB;
1628 /*
1629 * this hardware does not change the range of the samples
1630 * but since inside JPEG the YUV quantization is full-range,
1631 * this driver will always use full-range for the raw frames, too
1632 */
1633 pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;
1634
1635 return 0;
1636}
1637
1638static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
1639 struct v4l2_format *f)
1640{
1641 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
1642 struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
1643 struct device *dev = jpeg->dev;
Rikard Falkeborn7ec1c4a2021-06-12 01:42:01 +02001644 const struct mxc_jpeg_fmt *fmt;
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001645 u32 fourcc = f->fmt.pix_mp.pixelformat;
1646
1647 int q_type = (jpeg->mode == MXC_JPEG_DECODE) ?
1648 MXC_JPEG_FMT_TYPE_RAW : MXC_JPEG_FMT_TYPE_ENC;
1649
1650 if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
1651 dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);
1652 return -EINVAL;
1653 }
1654
1655 fmt = mxc_jpeg_find_format(ctx, fourcc);
1656 if (!fmt || fmt->flags != q_type) {
1657 dev_warn(dev, "Format not supported: %c%c%c%c, use the default.\n",
1658 (fourcc & 0xff),
1659 (fourcc >> 8) & 0xff,
1660 (fourcc >> 16) & 0xff,
1661 (fourcc >> 24) & 0xff);
1662 f->fmt.pix_mp.pixelformat = (jpeg->mode == MXC_JPEG_DECODE) ?
1663 MXC_JPEG_DEFAULT_PFMT : V4L2_PIX_FMT_JPEG;
1664 fmt = mxc_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat);
1665 }
1666 return mxc_jpeg_try_fmt(f, fmt, ctx, q_type);
1667}
1668
1669static int mxc_jpeg_try_fmt_vid_out(struct file *file, void *priv,
1670 struct v4l2_format *f)
1671{
1672 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
1673 struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
1674 struct device *dev = jpeg->dev;
Rikard Falkeborn7ec1c4a2021-06-12 01:42:01 +02001675 const struct mxc_jpeg_fmt *fmt;
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001676 u32 fourcc = f->fmt.pix_mp.pixelformat;
1677
1678 int q_type = (jpeg->mode == MXC_JPEG_ENCODE) ?
1679 MXC_JPEG_FMT_TYPE_RAW : MXC_JPEG_FMT_TYPE_ENC;
1680
1681 if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
1682 dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);
1683 return -EINVAL;
1684 }
1685
1686 fmt = mxc_jpeg_find_format(ctx, fourcc);
1687 if (!fmt || fmt->flags != q_type) {
1688 dev_warn(dev, "Format not supported: %c%c%c%c, use the default.\n",
1689 (fourcc & 0xff),
1690 (fourcc >> 8) & 0xff,
1691 (fourcc >> 16) & 0xff,
1692 (fourcc >> 24) & 0xff);
1693 f->fmt.pix_mp.pixelformat = (jpeg->mode == MXC_JPEG_ENCODE) ?
1694 MXC_JPEG_DEFAULT_PFMT : V4L2_PIX_FMT_JPEG;
1695 fmt = mxc_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat);
1696 }
1697 return mxc_jpeg_try_fmt(f, fmt, ctx, q_type);
1698}
1699
1700static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx,
1701 struct v4l2_format *f)
1702{
1703 struct vb2_queue *vq;
1704 struct mxc_jpeg_q_data *q_data = NULL;
1705 struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
1706 struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
1707 int i;
1708
1709 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
1710 if (!vq)
1711 return -EINVAL;
1712
1713 q_data = mxc_jpeg_get_q_data(ctx, f->type);
1714
1715 if (vb2_is_busy(vq)) {
1716 v4l2_err(&jpeg->v4l2_dev, "queue busy\n");
1717 return -EBUSY;
1718 }
1719
1720 q_data->fmt = mxc_jpeg_find_format(ctx, pix_mp->pixelformat);
1721 q_data->w = pix_mp->width;
1722 q_data->h = pix_mp->height;
1723
1724 q_data->w_adjusted = q_data->w;
1725 q_data->h_adjusted = q_data->h;
1726 if (jpeg->mode == MXC_JPEG_DECODE) {
1727 /*
1728 * align up the resolution for CAST IP,
1729 * but leave the buffer resolution unchanged
1730 */
1731 v4l_bound_align_image(&q_data->w_adjusted,
1732 q_data->w_adjusted, /* adjust upwards */
1733 MXC_JPEG_MAX_WIDTH,
1734 q_data->fmt->h_align,
1735 &q_data->h_adjusted,
1736 q_data->h_adjusted, /* adjust upwards */
1737 MXC_JPEG_MAX_HEIGHT,
1738 q_data->fmt->v_align,
1739 0);
1740 } else {
1741 /*
1742 * align down the resolution for CAST IP,
1743 * but leave the buffer resolution unchanged
1744 */
1745 v4l_bound_align_image(&q_data->w_adjusted,
1746 MXC_JPEG_MIN_WIDTH,
1747 q_data->w_adjusted, /* adjust downwards*/
1748 q_data->fmt->h_align,
1749 &q_data->h_adjusted,
1750 MXC_JPEG_MIN_HEIGHT,
1751 q_data->h_adjusted, /* adjust downwards*/
1752 q_data->fmt->v_align,
1753 0);
1754 }
1755
1756 for (i = 0; i < pix_mp->num_planes; i++) {
1757 q_data->bytesperline[i] = pix_mp->plane_fmt[i].bytesperline;
1758 q_data->sizeimage[i] = pix_mp->plane_fmt[i].sizeimage;
1759 }
1760
1761 return 0;
1762}
1763
1764static int mxc_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
1765 struct v4l2_format *f)
1766{
1767 int ret;
1768
1769 ret = mxc_jpeg_try_fmt_vid_cap(file, priv, f);
1770 if (ret)
1771 return ret;
1772
1773 return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
1774}
1775
1776static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv,
1777 struct v4l2_format *f)
1778{
1779 int ret;
1780
1781 ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
1782 if (ret)
1783 return ret;
1784
1785 return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
1786}
1787
1788static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,
1789 struct v4l2_format *f)
1790{
1791 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
1792 struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
1793 struct device *dev = jpeg->dev;
1794 struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
1795 struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);
1796 int i;
1797
1798 if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
1799 dev_err(dev, "G_FMT with Invalid type: %d\n", f->type);
1800 return -EINVAL;
1801 }
1802
1803 pix_mp->pixelformat = q_data->fmt->fourcc;
1804 pix_mp->width = q_data->w;
1805 pix_mp->height = q_data->h;
1806 pix_mp->field = V4L2_FIELD_NONE;
1807
1808 /* fix colorspace information to sRGB for both output & capture */
1809 pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
1810 pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601;
1811 pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB;
1812 pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;
1813
1814 pix_mp->num_planes = q_data->fmt->colplanes;
1815 for (i = 0; i < pix_mp->num_planes; i++) {
1816 pix_mp->plane_fmt[i].bytesperline = q_data->bytesperline[i];
1817 pix_mp->plane_fmt[i].sizeimage = q_data->sizeimage[i];
1818 }
1819
1820 return 0;
1821}
1822
1823static int mxc_jpeg_subscribe_event(struct v4l2_fh *fh,
1824 const struct v4l2_event_subscription *sub)
1825{
1826 switch (sub->type) {
1827 case V4L2_EVENT_EOS:
1828 return v4l2_event_subscribe(fh, sub, 0, NULL);
1829 case V4L2_EVENT_SOURCE_CHANGE:
1830 return v4l2_src_change_event_subscribe(fh, sub);
1831 default:
1832 return -EINVAL;
1833 }
1834}
1835
1836static int mxc_jpeg_dqbuf(struct file *file, void *priv,
1837 struct v4l2_buffer *buf)
1838{
1839 struct v4l2_fh *fh = file->private_data;
1840 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
1841 struct device *dev = ctx->mxc_jpeg->dev;
1842 int num_src_ready = v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx);
1843 int ret;
1844
1845 dev_dbg(dev, "DQBUF type=%d, index=%d", buf->type, buf->index);
1846 if (ctx->stopping == 1 && num_src_ready == 0) {
1847 /* No more src bufs, notify app EOS */
1848 notify_eos(ctx);
1849 ctx->stopping = 0;
1850 }
1851
1852 ret = v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf);
1853
1854 return ret;
1855}
1856
1857static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = {
1858 .vidioc_querycap = mxc_jpeg_querycap,
1859 .vidioc_enum_fmt_vid_cap = mxc_jpeg_enum_fmt_vid_cap,
1860 .vidioc_enum_fmt_vid_out = mxc_jpeg_enum_fmt_vid_out,
1861
1862 .vidioc_try_fmt_vid_cap_mplane = mxc_jpeg_try_fmt_vid_cap,
1863 .vidioc_try_fmt_vid_out_mplane = mxc_jpeg_try_fmt_vid_out,
1864
1865 .vidioc_s_fmt_vid_cap_mplane = mxc_jpeg_s_fmt_vid_cap,
1866 .vidioc_s_fmt_vid_out_mplane = mxc_jpeg_s_fmt_vid_out,
1867
1868 .vidioc_g_fmt_vid_cap_mplane = mxc_jpeg_g_fmt_vid,
1869 .vidioc_g_fmt_vid_out_mplane = mxc_jpeg_g_fmt_vid,
1870
1871 .vidioc_subscribe_event = mxc_jpeg_subscribe_event,
1872 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1873
1874 .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
1875 .vidioc_decoder_cmd = mxc_jpeg_decoder_cmd,
1876 .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
1877 .vidioc_encoder_cmd = mxc_jpeg_encoder_cmd,
1878
1879 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1880 .vidioc_dqbuf = mxc_jpeg_dqbuf,
1881
1882 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
1883 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
1884 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1885 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1886 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
1887 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
1888 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
1889};
1890
1891static int mxc_jpeg_release(struct file *file)
1892{
1893 struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
1894 struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(file->private_data);
1895 struct device *dev = mxc_jpeg->dev;
1896
1897 mutex_lock(&mxc_jpeg->lock);
1898 if (mxc_jpeg->mode == MXC_JPEG_DECODE)
1899 dev_dbg(dev, "Release JPEG decoder instance on slot %d.",
1900 ctx->slot);
1901 else
1902 dev_dbg(dev, "Release JPEG encoder instance on slot %d.",
1903 ctx->slot);
1904 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
1905 v4l2_fh_del(&ctx->fh);
1906 v4l2_fh_exit(&ctx->fh);
1907 kfree(ctx);
1908 mutex_unlock(&mxc_jpeg->lock);
1909
1910 return 0;
1911}
1912
1913static const struct v4l2_file_operations mxc_jpeg_fops = {
1914 .owner = THIS_MODULE,
1915 .open = mxc_jpeg_open,
1916 .release = mxc_jpeg_release,
1917 .poll = v4l2_m2m_fop_poll,
1918 .unlocked_ioctl = video_ioctl2,
1919 .mmap = v4l2_m2m_fop_mmap,
1920};
1921
Rikard Falkeborn682e69d2021-06-12 01:42:00 +02001922static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = {
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001923 .device_run = mxc_jpeg_device_run,
1924};
1925
1926static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg)
1927{
1928 int i;
1929
1930 for (i = 0; i < jpeg->num_domains; i++) {
1931 if (jpeg->pd_link[i] && !IS_ERR(jpeg->pd_link[i]))
1932 device_link_del(jpeg->pd_link[i]);
1933 if (jpeg->pd_dev[i] && !IS_ERR(jpeg->pd_dev[i]))
1934 dev_pm_domain_detach(jpeg->pd_dev[i], true);
1935 jpeg->pd_dev[i] = NULL;
1936 jpeg->pd_link[i] = NULL;
1937 }
1938}
1939
1940static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg)
1941{
1942 struct device *dev = jpeg->dev;
1943 struct device_node *np = jpeg->pdev->dev.of_node;
1944 int i;
1945 int ret;
1946
1947 jpeg->num_domains = of_count_phandle_with_args(np, "power-domains",
1948 "#power-domain-cells");
1949 if (jpeg->num_domains < 0) {
1950 dev_err(dev, "No power domains defined for jpeg node\n");
1951 return jpeg->num_domains;
1952 }
1953
1954 jpeg->pd_dev = devm_kmalloc_array(dev, jpeg->num_domains,
1955 sizeof(*jpeg->pd_dev), GFP_KERNEL);
1956 if (!jpeg->pd_dev)
1957 return -ENOMEM;
1958
1959 jpeg->pd_link = devm_kmalloc_array(dev, jpeg->num_domains,
1960 sizeof(*jpeg->pd_link), GFP_KERNEL);
1961 if (!jpeg->pd_link)
1962 return -ENOMEM;
1963
1964 for (i = 0; i < jpeg->num_domains; i++) {
1965 jpeg->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
1966 if (IS_ERR(jpeg->pd_dev[i])) {
1967 ret = PTR_ERR(jpeg->pd_dev[i]);
1968 goto fail;
1969 }
1970
1971 jpeg->pd_link[i] = device_link_add(dev, jpeg->pd_dev[i],
1972 DL_FLAG_STATELESS |
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01001973 DL_FLAG_PM_RUNTIME);
Wei Yongjund75b3282021-03-23 12:29:03 +01001974 if (!jpeg->pd_link[i]) {
1975 ret = -EINVAL;
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001976 goto fail;
1977 }
1978 }
1979
1980 return 0;
1981fail:
1982 mxc_jpeg_detach_pm_domains(jpeg);
1983 return ret;
1984}
1985
1986static int mxc_jpeg_probe(struct platform_device *pdev)
1987{
1988 struct mxc_jpeg_dev *jpeg;
1989 struct device *dev = &pdev->dev;
Mirela Rabulea2db16c62021-03-11 09:53:17 +01001990 int dec_irq;
1991 int ret;
1992 int mode;
1993 const struct of_device_id *of_id;
1994 unsigned int slot;
1995
1996 of_id = of_match_node(mxc_jpeg_match, dev->of_node);
1997 mode = *(const int *)of_id->data;
1998
1999 jpeg = devm_kzalloc(dev, sizeof(struct mxc_jpeg_dev), GFP_KERNEL);
2000 if (!jpeg)
2001 return -ENOMEM;
2002
2003 mutex_init(&jpeg->lock);
2004 spin_lock_init(&jpeg->hw_lock);
2005
2006 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
2007 if (ret) {
2008 dev_err(&pdev->dev, "No suitable DMA available.\n");
2009 goto err_irq;
2010 }
2011
Cai Huoqinga498a4e2021-09-01 07:51:38 +02002012 jpeg->base_reg = devm_platform_ioremap_resource(pdev, 0);
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002013 if (IS_ERR(jpeg->base_reg))
2014 return PTR_ERR(jpeg->base_reg);
2015
2016 for (slot = 0; slot < MXC_MAX_SLOTS; slot++) {
2017 dec_irq = platform_get_irq(pdev, slot);
2018 if (dec_irq < 0) {
2019 dev_err(&pdev->dev, "Failed to get irq %d\n", dec_irq);
2020 ret = dec_irq;
2021 goto err_irq;
2022 }
2023 ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
2024 0, pdev->name, jpeg);
2025 if (ret) {
2026 dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
2027 dec_irq, ret);
2028 goto err_irq;
2029 }
2030 }
2031
2032 jpeg->pdev = pdev;
2033 jpeg->dev = dev;
2034 jpeg->mode = mode;
2035
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01002036 /* Get clocks */
2037 jpeg->clk_ipg = devm_clk_get(dev, "ipg");
2038 if (IS_ERR(jpeg->clk_ipg)) {
2039 dev_err(dev, "failed to get clock: ipg\n");
2040 goto err_clk;
2041 }
2042
2043 jpeg->clk_per = devm_clk_get(dev, "per");
2044 if (IS_ERR(jpeg->clk_per)) {
2045 dev_err(dev, "failed to get clock: per\n");
2046 goto err_clk;
2047 }
2048
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002049 ret = mxc_jpeg_attach_pm_domains(jpeg);
2050 if (ret < 0) {
2051 dev_err(dev, "failed to attach power domains %d\n", ret);
2052 return ret;
2053 }
2054
2055 /* v4l2 */
2056 ret = v4l2_device_register(dev, &jpeg->v4l2_dev);
2057 if (ret) {
2058 dev_err(dev, "failed to register v4l2 device\n");
2059 goto err_register;
2060 }
2061 jpeg->m2m_dev = v4l2_m2m_init(&mxc_jpeg_m2m_ops);
2062 if (IS_ERR(jpeg->m2m_dev)) {
2063 dev_err(dev, "failed to register v4l2 device\n");
Wei Yongjunfb3b5972021-03-23 12:28:55 +01002064 ret = PTR_ERR(jpeg->m2m_dev);
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002065 goto err_m2m;
2066 }
2067
2068 jpeg->dec_vdev = video_device_alloc();
2069 if (!jpeg->dec_vdev) {
2070 dev_err(dev, "failed to register v4l2 device\n");
Wei Yongjunfb3b5972021-03-23 12:28:55 +01002071 ret = -ENOMEM;
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002072 goto err_vdev_alloc;
2073 }
2074 if (mode == MXC_JPEG_ENCODE)
2075 snprintf(jpeg->dec_vdev->name,
2076 sizeof(jpeg->dec_vdev->name),
2077 "%s-enc", MXC_JPEG_NAME);
2078 else
2079 snprintf(jpeg->dec_vdev->name,
2080 sizeof(jpeg->dec_vdev->name),
2081 "%s-dec", MXC_JPEG_NAME);
2082
2083 jpeg->dec_vdev->fops = &mxc_jpeg_fops;
2084 jpeg->dec_vdev->ioctl_ops = &mxc_jpeg_ioctl_ops;
2085 jpeg->dec_vdev->minor = -1;
2086 jpeg->dec_vdev->release = video_device_release;
2087 jpeg->dec_vdev->lock = &jpeg->lock; /* lock for ioctl serialization */
2088 jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;
2089 jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
2090 jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |
2091 V4L2_CAP_VIDEO_M2M_MPLANE;
2092 if (mode == MXC_JPEG_ENCODE) {
2093 v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_DECODER_CMD);
2094 v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_DECODER_CMD);
2095 } else {
2096 v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_ENCODER_CMD);
2097 v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_ENCODER_CMD);
2098 }
2099 ret = video_register_device(jpeg->dec_vdev, VFL_TYPE_VIDEO, -1);
2100 if (ret) {
2101 dev_err(dev, "failed to register video device\n");
2102 goto err_vdev_register;
2103 }
2104 video_set_drvdata(jpeg->dec_vdev, jpeg);
2105 if (mode == MXC_JPEG_ENCODE)
2106 v4l2_info(&jpeg->v4l2_dev,
2107 "encoder device registered as /dev/video%d (%d,%d)\n",
2108 jpeg->dec_vdev->num, VIDEO_MAJOR,
2109 jpeg->dec_vdev->minor);
2110 else
2111 v4l2_info(&jpeg->v4l2_dev,
2112 "decoder device registered as /dev/video%d (%d,%d)\n",
2113 jpeg->dec_vdev->num, VIDEO_MAJOR,
2114 jpeg->dec_vdev->minor);
2115
2116 platform_set_drvdata(pdev, jpeg);
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01002117 pm_runtime_enable(dev);
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002118
2119 return 0;
2120
2121err_vdev_register:
2122 video_device_release(jpeg->dec_vdev);
2123
2124err_vdev_alloc:
2125 v4l2_m2m_release(jpeg->m2m_dev);
2126
2127err_m2m:
2128 v4l2_device_unregister(&jpeg->v4l2_dev);
2129
2130err_register:
Christophe JAILLET5c47dc62021-08-21 13:12:53 +02002131 mxc_jpeg_detach_pm_domains(jpeg);
2132
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002133err_irq:
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01002134err_clk:
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002135 return ret;
2136}
2137
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01002138#ifdef CONFIG_PM
2139static int mxc_jpeg_runtime_resume(struct device *dev)
2140{
2141 struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
2142 int ret;
2143
2144 ret = clk_prepare_enable(jpeg->clk_ipg);
2145 if (ret < 0) {
2146 dev_err(dev, "failed to enable clock: ipg\n");
2147 goto err_ipg;
2148 }
2149
2150 ret = clk_prepare_enable(jpeg->clk_per);
2151 if (ret < 0) {
2152 dev_err(dev, "failed to enable clock: per\n");
2153 goto err_per;
2154 }
2155
2156 return 0;
2157
2158err_per:
2159 clk_disable_unprepare(jpeg->clk_ipg);
2160err_ipg:
2161 return ret;
2162}
2163
2164static int mxc_jpeg_runtime_suspend(struct device *dev)
2165{
2166 struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
2167
2168 clk_disable_unprepare(jpeg->clk_ipg);
2169 clk_disable_unprepare(jpeg->clk_per);
2170
2171 return 0;
2172}
2173#endif
2174
2175static const struct dev_pm_ops mxc_jpeg_pm_ops = {
2176 SET_RUNTIME_PM_OPS(mxc_jpeg_runtime_suspend,
2177 mxc_jpeg_runtime_resume, NULL)
2178};
2179
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002180static int mxc_jpeg_remove(struct platform_device *pdev)
2181{
2182 unsigned int slot;
2183 struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev);
2184
2185 for (slot = 0; slot < MXC_MAX_SLOTS; slot++)
2186 mxc_jpeg_free_slot_data(jpeg, slot);
2187
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01002188 pm_runtime_disable(&pdev->dev);
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002189 video_unregister_device(jpeg->dec_vdev);
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002190 v4l2_m2m_release(jpeg->m2m_dev);
2191 v4l2_device_unregister(&jpeg->v4l2_dev);
2192 mxc_jpeg_detach_pm_domains(jpeg);
2193
2194 return 0;
2195}
2196
2197MODULE_DEVICE_TABLE(of, mxc_jpeg_match);
2198
2199static struct platform_driver mxc_jpeg_driver = {
2200 .probe = mxc_jpeg_probe,
2201 .remove = mxc_jpeg_remove,
2202 .driver = {
2203 .name = "mxc-jpeg",
2204 .of_match_table = mxc_jpeg_match,
Mirela Rabulea4c2e5152021-10-07 17:30:38 +01002205 .pm = &mxc_jpeg_pm_ops,
Mirela Rabulea2db16c62021-03-11 09:53:17 +01002206 },
2207};
2208module_platform_driver(mxc_jpeg_driver);
2209
2210MODULE_AUTHOR("Zhengyu Shen <zhengyu.shen_1@nxp.com>");
2211MODULE_AUTHOR("Mirela Rabulea <mirela.rabulea@nxp.com>");
2212MODULE_DESCRIPTION("V4L2 driver for i.MX8 QXP/QM JPEG encoder/decoder");
2213MODULE_LICENSE("GPL v2");