diff options
author | Hugues Fruchet <hugues.fruchet@st.com> | 2017-02-02 09:59:48 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-02-08 07:00:27 -0500 |
commit | f386509e49594591f80af2e5a73d4c9ce389aa29 (patch) | |
tree | c6459059b2d65f94b472bbcd5b65f3136ff4e191 | |
parent | f34b87e486c5e2b219b1e21084299855ca25a05d (diff) |
[media] st-delta: STiH4xx multi-format video decoder v4l2 driver
This V4L2 driver enables DELTA multi-format video decoder
of STMicroelectronics STiH4xx SoC series.
Acked-by: Peter Griffin <peter.griffin@linaro.org>
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r-- | drivers/media/platform/Kconfig | 28 | ||||
-rw-r--r-- | drivers/media/platform/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/platform/sti/delta/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/platform/sti/delta/delta-cfg.h | 61 | ||||
-rw-r--r-- | drivers/media/platform/sti/delta/delta-v4l2.c | 1813 | ||||
-rw-r--r-- | drivers/media/platform/sti/delta/delta.h | 514 |
6 files changed, 2420 insertions, 0 deletions
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 0245af0b76e0..863c61a0895e 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig | |||
@@ -312,6 +312,34 @@ config VIDEO_STI_HVA_DEBUGFS | |||
312 | 312 | ||
313 | Choose N unless you know you need this. | 313 | Choose N unless you know you need this. |
314 | 314 | ||
315 | config VIDEO_STI_DELTA | ||
316 | tristate "STMicroelectronics DELTA multi-format video decoder V4L2 driver" | ||
317 | depends on VIDEO_DEV && VIDEO_V4L2 | ||
318 | depends on ARCH_STI || COMPILE_TEST | ||
319 | depends on HAS_DMA | ||
320 | help | ||
321 | This V4L2 driver enables DELTA multi-format video decoder | ||
322 | of STMicroelectronics STiH4xx SoC series allowing hardware | ||
323 | decoding of various compressed video bitstream format in | ||
324 | raw uncompressed format. | ||
325 | |||
326 | Use this option to see the decoders available for such | ||
327 | hardware. | ||
328 | |||
329 | Please notice that the driver will only be built if | ||
330 | at least one of the DELTA decoder below is selected. | ||
331 | |||
332 | if VIDEO_STI_DELTA | ||
333 | |||
334 | config VIDEO_STI_DELTA_DRIVER | ||
335 | tristate | ||
336 | depends on VIDEO_STI_DELTA | ||
337 | default n | ||
338 | select VIDEOBUF2_DMA_CONTIG | ||
339 | select V4L2_MEM2MEM_DEV | ||
340 | |||
341 | endif # VIDEO_STI_DELTA | ||
342 | |||
315 | config VIDEO_SH_VEU | 343 | config VIDEO_SH_VEU |
316 | tristate "SuperH VEU mem2mem video processing driver" | 344 | tristate "SuperH VEU mem2mem video processing driver" |
317 | depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA | 345 | depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA |
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 5b3cb271d2b8..349ddf6a69da 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile | |||
@@ -39,6 +39,8 @@ obj-$(CONFIG_VIDEO_STI_BDISP) += sti/bdisp/ | |||
39 | obj-$(CONFIG_VIDEO_STI_HVA) += sti/hva/ | 39 | obj-$(CONFIG_VIDEO_STI_HVA) += sti/hva/ |
40 | obj-$(CONFIG_DVB_C8SECTPFE) += sti/c8sectpfe/ | 40 | obj-$(CONFIG_DVB_C8SECTPFE) += sti/c8sectpfe/ |
41 | 41 | ||
42 | obj-$(CONFIG_VIDEO_STI_DELTA) += sti/delta/ | ||
43 | |||
42 | obj-$(CONFIG_BLACKFIN) += blackfin/ | 44 | obj-$(CONFIG_BLACKFIN) += blackfin/ |
43 | 45 | ||
44 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | 46 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ |
diff --git a/drivers/media/platform/sti/delta/Makefile b/drivers/media/platform/sti/delta/Makefile new file mode 100644 index 000000000000..467519e12ba5 --- /dev/null +++ b/drivers/media/platform/sti/delta/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-$(CONFIG_VIDEO_STI_DELTA_DRIVER) := st-delta.o | ||
2 | st-delta-y := delta-v4l2.o | ||
diff --git a/drivers/media/platform/sti/delta/delta-cfg.h b/drivers/media/platform/sti/delta/delta-cfg.h new file mode 100644 index 000000000000..f6674f6dcd37 --- /dev/null +++ b/drivers/media/platform/sti/delta/delta-cfg.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2015 | ||
3 | * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics. | ||
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | ||
6 | |||
7 | #ifndef DELTA_CFG_H | ||
8 | #define DELTA_CFG_H | ||
9 | |||
10 | #define DELTA_FW_VERSION "21.1-3" | ||
11 | |||
12 | #define DELTA_MIN_WIDTH 32 | ||
13 | #define DELTA_MAX_WIDTH 4096 | ||
14 | #define DELTA_MIN_HEIGHT 32 | ||
15 | #define DELTA_MAX_HEIGHT 2400 | ||
16 | |||
17 | /* DELTA requires a 32x32 pixels alignment for frames */ | ||
18 | #define DELTA_WIDTH_ALIGNMENT 32 | ||
19 | #define DELTA_HEIGHT_ALIGNMENT 32 | ||
20 | |||
21 | #define DELTA_DEFAULT_WIDTH DELTA_MIN_WIDTH | ||
22 | #define DELTA_DEFAULT_HEIGHT DELTA_MIN_HEIGHT | ||
23 | #define DELTA_DEFAULT_FRAMEFORMAT V4L2_PIX_FMT_NV12 | ||
24 | #define DELTA_DEFAULT_STREAMFORMAT V4L2_PIX_FMT_MJPEG | ||
25 | |||
26 | #define DELTA_MAX_RESO (DELTA_MAX_WIDTH * DELTA_MAX_HEIGHT) | ||
27 | |||
28 | /* guard value for number of access units */ | ||
29 | #define DELTA_MAX_AUS 10 | ||
30 | |||
31 | /* IP perf dependent, can be tuned */ | ||
32 | #define DELTA_PEAK_FRAME_SMOOTHING 2 | ||
33 | |||
34 | /* | ||
35 | * guard output frame count: | ||
36 | * - at least 1 frame needed for display | ||
37 | * - at worst 21 | ||
38 | * ( max h264 dpb (16) + | ||
39 | * decoding peak smoothing (2) + | ||
40 | * user display pipeline (3) ) | ||
41 | */ | ||
42 | #define DELTA_MIN_FRAME_USER 1 | ||
43 | #define DELTA_MAX_DPB 16 | ||
44 | #define DELTA_MAX_FRAME_USER 3 /* platform/use-case dependent */ | ||
45 | #define DELTA_MAX_FRAMES (DELTA_MAX_DPB + DELTA_PEAK_FRAME_SMOOTHING +\ | ||
46 | DELTA_MAX_FRAME_USER) | ||
47 | |||
48 | #if DELTA_MAX_FRAMES > VIDEO_MAX_FRAME | ||
49 | #undef DELTA_MAX_FRAMES | ||
50 | #define DELTA_MAX_FRAMES (VIDEO_MAX_FRAME) | ||
51 | #endif | ||
52 | |||
53 | /* extra space to be allocated to store codec specific data per frame */ | ||
54 | #define DELTA_MAX_FRAME_PRIV_SIZE 100 | ||
55 | |||
56 | /* PM runtime auto power-off after 5ms of inactivity */ | ||
57 | #define DELTA_HW_AUTOSUSPEND_DELAY_MS 5 | ||
58 | |||
59 | #define DELTA_MAX_DECODERS 10 | ||
60 | |||
61 | #endif /* DELTA_CFG_H */ | ||
diff --git a/drivers/media/platform/sti/delta/delta-v4l2.c b/drivers/media/platform/sti/delta/delta-v4l2.c new file mode 100644 index 000000000000..e65a3a327724 --- /dev/null +++ b/drivers/media/platform/sti/delta/delta-v4l2.c | |||
@@ -0,0 +1,1813 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2015 | ||
3 | * Authors: Hugues Fruchet <hugues.fruchet@st.com> | ||
4 | * Jean-Christophe Trotin <jean-christophe.trotin@st.com> | ||
5 | * for STMicroelectronics. | ||
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | ||
8 | |||
9 | #include <linux/clk.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/pm_runtime.h> | ||
13 | #include <linux/slab.h> | ||
14 | |||
15 | #include <media/v4l2-ioctl.h> | ||
16 | #include <media/v4l2-event.h> | ||
17 | #include <media/videobuf2-dma-contig.h> | ||
18 | |||
19 | #include "delta.h" | ||
20 | |||
21 | #define DELTA_NAME "st-delta" | ||
22 | |||
23 | #define DELTA_PREFIX "[---:----]" | ||
24 | |||
25 | #define to_ctx(__fh) container_of(__fh, struct delta_ctx, fh) | ||
26 | #define to_au(__vbuf) container_of(__vbuf, struct delta_au, vbuf) | ||
27 | #define to_frame(__vbuf) container_of(__vbuf, struct delta_frame, vbuf) | ||
28 | |||
29 | #define call_dec_op(dec, op, args...)\ | ||
30 | ((dec && (dec)->op) ? (dec)->op(args) : 0) | ||
31 | |||
32 | /* registry of available decoders */ | ||
33 | static const struct delta_dec *delta_decoders[] = { | ||
34 | }; | ||
35 | |||
36 | static inline int frame_size(u32 w, u32 h, u32 fmt) | ||
37 | { | ||
38 | switch (fmt) { | ||
39 | case V4L2_PIX_FMT_NV12: | ||
40 | return (w * h * 3) / 2; | ||
41 | default: | ||
42 | return 0; | ||
43 | } | ||
44 | } | ||
45 | |||
46 | static inline int frame_stride(u32 w, u32 fmt) | ||
47 | { | ||
48 | switch (fmt) { | ||
49 | case V4L2_PIX_FMT_NV12: | ||
50 | return w; | ||
51 | default: | ||
52 | return 0; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | static void dump_au(struct delta_ctx *ctx, struct delta_au *au) | ||
57 | { | ||
58 | struct delta_dev *delta = ctx->dev; | ||
59 | u32 size = 10; /* dump first & last 10 bytes */ | ||
60 | u8 *data = (u8 *)(au->vaddr); | ||
61 | |||
62 | if (au->size <= (size * 2)) | ||
63 | dev_dbg(delta->dev, "%s dump au[%d] dts=%lld size=%d data=%*ph\n", | ||
64 | ctx->name, au->vbuf.vb2_buf.index, au->dts, au->size, | ||
65 | au->size, data); | ||
66 | else | ||
67 | dev_dbg(delta->dev, "%s dump au[%d] dts=%lld size=%d data=%*ph..%*ph\n", | ||
68 | ctx->name, au->vbuf.vb2_buf.index, au->dts, au->size, | ||
69 | size, data, size, data + au->size - size); | ||
70 | } | ||
71 | |||
72 | static void dump_frame(struct delta_ctx *ctx, struct delta_frame *frame) | ||
73 | { | ||
74 | struct delta_dev *delta = ctx->dev; | ||
75 | u32 size = 10; /* dump first 10 bytes */ | ||
76 | u8 *data = (u8 *)(frame->vaddr); | ||
77 | |||
78 | dev_dbg(delta->dev, "%s dump frame[%d] dts=%lld type=%s field=%s data=%*ph\n", | ||
79 | ctx->name, frame->index, frame->dts, | ||
80 | frame_type_str(frame->flags), | ||
81 | frame_field_str(frame->field), | ||
82 | size, data); | ||
83 | } | ||
84 | |||
85 | static void delta_au_done(struct delta_ctx *ctx, struct delta_au *au, int err) | ||
86 | { | ||
87 | struct vb2_v4l2_buffer *vbuf; | ||
88 | |||
89 | vbuf = &au->vbuf; | ||
90 | vbuf->sequence = ctx->au_num++; | ||
91 | v4l2_m2m_buf_done(vbuf, err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); | ||
92 | } | ||
93 | |||
94 | static void delta_frame_done(struct delta_ctx *ctx, struct delta_frame *frame, | ||
95 | int err) | ||
96 | { | ||
97 | struct vb2_v4l2_buffer *vbuf; | ||
98 | |||
99 | dump_frame(ctx, frame); | ||
100 | |||
101 | /* decoded frame is now output to user */ | ||
102 | frame->state |= DELTA_FRAME_OUT; | ||
103 | |||
104 | vbuf = &frame->vbuf; | ||
105 | vbuf->sequence = ctx->frame_num++; | ||
106 | v4l2_m2m_buf_done(vbuf, err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); | ||
107 | |||
108 | ctx->output_frames++; | ||
109 | } | ||
110 | |||
111 | static void requeue_free_frames(struct delta_ctx *ctx) | ||
112 | { | ||
113 | struct vb2_v4l2_buffer *vbuf; | ||
114 | struct delta_frame *frame; | ||
115 | unsigned int i; | ||
116 | |||
117 | /* requeue all free frames */ | ||
118 | for (i = 0; i < ctx->nb_of_frames; i++) { | ||
119 | frame = ctx->frames[i]; | ||
120 | if (frame->state == DELTA_FRAME_FREE) { | ||
121 | vbuf = &frame->vbuf; | ||
122 | v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); | ||
123 | frame->state = DELTA_FRAME_M2M; | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | static int delta_recycle(struct delta_ctx *ctx, struct delta_frame *frame) | ||
129 | { | ||
130 | const struct delta_dec *dec = ctx->dec; | ||
131 | |||
132 | /* recycle frame on decoder side */ | ||
133 | call_dec_op(dec, recycle, ctx, frame); | ||
134 | |||
135 | /* this frame is no more output */ | ||
136 | frame->state &= ~DELTA_FRAME_OUT; | ||
137 | |||
138 | /* requeue free frame */ | ||
139 | if (frame->state == DELTA_FRAME_FREE) { | ||
140 | struct vb2_v4l2_buffer *vbuf = &frame->vbuf; | ||
141 | |||
142 | v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); | ||
143 | frame->state = DELTA_FRAME_M2M; | ||
144 | } | ||
145 | |||
146 | /* reset other frame fields */ | ||
147 | frame->flags = 0; | ||
148 | frame->dts = 0; | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void delta_push_dts(struct delta_ctx *ctx, u64 val) | ||
154 | { | ||
155 | struct delta_dts *dts; | ||
156 | |||
157 | dts = kzalloc(sizeof(*dts), GFP_KERNEL); | ||
158 | if (!dts) | ||
159 | return; | ||
160 | |||
161 | INIT_LIST_HEAD(&dts->list); | ||
162 | |||
163 | /* | ||
164 | * protected by global lock acquired | ||
165 | * by V4L2 when calling delta_vb2_au_queue | ||
166 | */ | ||
167 | dts->val = val; | ||
168 | list_add_tail(&dts->list, &ctx->dts); | ||
169 | } | ||
170 | |||
171 | static void delta_pop_dts(struct delta_ctx *ctx, u64 *val) | ||
172 | { | ||
173 | struct delta_dev *delta = ctx->dev; | ||
174 | struct delta_dts *dts; | ||
175 | |||
176 | /* | ||
177 | * protected by global lock acquired | ||
178 | * by V4L2 when calling delta_vb2_au_queue | ||
179 | */ | ||
180 | if (list_empty(&ctx->dts)) { | ||
181 | dev_warn(delta->dev, "%s no dts to pop ... output dts = 0\n", | ||
182 | ctx->name); | ||
183 | *val = 0; | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | dts = list_first_entry(&ctx->dts, struct delta_dts, list); | ||
188 | list_del(&dts->list); | ||
189 | |||
190 | *val = dts->val; | ||
191 | |||
192 | kfree(dts); | ||
193 | } | ||
194 | |||
195 | static void delta_flush_dts(struct delta_ctx *ctx) | ||
196 | { | ||
197 | struct delta_dts *dts; | ||
198 | struct delta_dts *next; | ||
199 | |||
200 | /* | ||
201 | * protected by global lock acquired | ||
202 | * by V4L2 when calling delta_vb2_au_queue | ||
203 | */ | ||
204 | |||
205 | /* free all pending dts */ | ||
206 | list_for_each_entry_safe(dts, next, &ctx->dts, list) | ||
207 | kfree(dts); | ||
208 | |||
209 | /* reset list */ | ||
210 | INIT_LIST_HEAD(&ctx->dts); | ||
211 | } | ||
212 | |||
213 | static inline int frame_alignment(u32 fmt) | ||
214 | { | ||
215 | switch (fmt) { | ||
216 | case V4L2_PIX_FMT_NV12: | ||
217 | case V4L2_PIX_FMT_NV21: | ||
218 | /* multiple of 2 */ | ||
219 | return 2; | ||
220 | default: | ||
221 | return 1; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static inline int estimated_au_size(u32 w, u32 h) | ||
226 | { | ||
227 | /* | ||
228 | * for a MJPEG stream encoded from YUV422 pixel format, | ||
229 | * assuming a compression ratio of 2, the maximum size | ||
230 | * of an access unit is (width x height x 2) / 2, | ||
231 | * so (width x height) | ||
232 | */ | ||
233 | return (w * h); | ||
234 | } | ||
235 | |||
236 | static void set_default_params(struct delta_ctx *ctx) | ||
237 | { | ||
238 | struct delta_frameinfo *frameinfo = &ctx->frameinfo; | ||
239 | struct delta_streaminfo *streaminfo = &ctx->streaminfo; | ||
240 | |||
241 | memset(frameinfo, 0, sizeof(*frameinfo)); | ||
242 | frameinfo->pixelformat = V4L2_PIX_FMT_NV12; | ||
243 | frameinfo->width = DELTA_DEFAULT_WIDTH; | ||
244 | frameinfo->height = DELTA_DEFAULT_HEIGHT; | ||
245 | frameinfo->aligned_width = ALIGN(frameinfo->width, | ||
246 | DELTA_WIDTH_ALIGNMENT); | ||
247 | frameinfo->aligned_height = ALIGN(frameinfo->height, | ||
248 | DELTA_HEIGHT_ALIGNMENT); | ||
249 | frameinfo->size = frame_size(frameinfo->aligned_width, | ||
250 | frameinfo->aligned_height, | ||
251 | frameinfo->pixelformat); | ||
252 | frameinfo->field = V4L2_FIELD_NONE; | ||
253 | frameinfo->colorspace = V4L2_COLORSPACE_REC709; | ||
254 | frameinfo->xfer_func = V4L2_XFER_FUNC_DEFAULT; | ||
255 | frameinfo->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | ||
256 | frameinfo->quantization = V4L2_QUANTIZATION_DEFAULT; | ||
257 | |||
258 | memset(streaminfo, 0, sizeof(*streaminfo)); | ||
259 | streaminfo->streamformat = DELTA_DEFAULT_STREAMFORMAT; | ||
260 | streaminfo->width = DELTA_DEFAULT_WIDTH; | ||
261 | streaminfo->height = DELTA_DEFAULT_HEIGHT; | ||
262 | streaminfo->field = V4L2_FIELD_NONE; | ||
263 | streaminfo->colorspace = V4L2_COLORSPACE_REC709; | ||
264 | streaminfo->xfer_func = V4L2_XFER_FUNC_DEFAULT; | ||
265 | streaminfo->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | ||
266 | streaminfo->quantization = V4L2_QUANTIZATION_DEFAULT; | ||
267 | |||
268 | ctx->max_au_size = estimated_au_size(streaminfo->width, | ||
269 | streaminfo->height); | ||
270 | } | ||
271 | |||
272 | static const struct delta_dec *delta_find_decoder(struct delta_ctx *ctx, | ||
273 | u32 streamformat, | ||
274 | u32 pixelformat) | ||
275 | { | ||
276 | struct delta_dev *delta = ctx->dev; | ||
277 | const struct delta_dec *dec; | ||
278 | unsigned int i; | ||
279 | |||
280 | for (i = 0; i < delta->nb_of_decoders; i++) { | ||
281 | dec = delta->decoders[i]; | ||
282 | if ((dec->pixelformat == pixelformat) && | ||
283 | (dec->streamformat == streamformat)) | ||
284 | return dec; | ||
285 | } | ||
286 | |||
287 | return NULL; | ||
288 | } | ||
289 | |||
290 | static void register_format(u32 format, u32 formats[], u32 *nb_of_formats) | ||
291 | { | ||
292 | u32 i; | ||
293 | |||
294 | for (i = 0; i < *nb_of_formats; i++) { | ||
295 | if (format == formats[i]) | ||
296 | return; | ||
297 | } | ||
298 | |||
299 | formats[(*nb_of_formats)++] = format; | ||
300 | } | ||
301 | |||
302 | static void register_formats(struct delta_dev *delta) | ||
303 | { | ||
304 | unsigned int i; | ||
305 | |||
306 | for (i = 0; i < delta->nb_of_decoders; i++) { | ||
307 | register_format(delta->decoders[i]->pixelformat, | ||
308 | delta->pixelformats, | ||
309 | &delta->nb_of_pixelformats); | ||
310 | |||
311 | register_format(delta->decoders[i]->streamformat, | ||
312 | delta->streamformats, | ||
313 | &delta->nb_of_streamformats); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | static void register_decoders(struct delta_dev *delta) | ||
318 | { | ||
319 | unsigned int i; | ||
320 | |||
321 | for (i = 0; i < ARRAY_SIZE(delta_decoders); i++) { | ||
322 | if (delta->nb_of_decoders >= DELTA_MAX_DECODERS) { | ||
323 | dev_dbg(delta->dev, | ||
324 | "%s failed to register %s decoder (%d maximum reached)\n", | ||
325 | DELTA_PREFIX, delta_decoders[i]->name, | ||
326 | DELTA_MAX_DECODERS); | ||
327 | return; | ||
328 | } | ||
329 | |||
330 | delta->decoders[delta->nb_of_decoders++] = delta_decoders[i]; | ||
331 | dev_info(delta->dev, "%s %s decoder registered\n", | ||
332 | DELTA_PREFIX, delta_decoders[i]->name); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static void delta_lock(void *priv) | ||
337 | { | ||
338 | struct delta_ctx *ctx = priv; | ||
339 | struct delta_dev *delta = ctx->dev; | ||
340 | |||
341 | mutex_lock(&delta->lock); | ||
342 | } | ||
343 | |||
344 | static void delta_unlock(void *priv) | ||
345 | { | ||
346 | struct delta_ctx *ctx = priv; | ||
347 | struct delta_dev *delta = ctx->dev; | ||
348 | |||
349 | mutex_unlock(&delta->lock); | ||
350 | } | ||
351 | |||
352 | static int delta_open_decoder(struct delta_ctx *ctx, u32 streamformat, | ||
353 | u32 pixelformat, const struct delta_dec **pdec) | ||
354 | { | ||
355 | struct delta_dev *delta = ctx->dev; | ||
356 | const struct delta_dec *dec; | ||
357 | int ret; | ||
358 | |||
359 | dec = delta_find_decoder(ctx, streamformat, ctx->frameinfo.pixelformat); | ||
360 | if (!dec) { | ||
361 | dev_err(delta->dev, "%s no decoder found matching %4.4s => %4.4s\n", | ||
362 | ctx->name, (char *)&streamformat, (char *)&pixelformat); | ||
363 | return -EINVAL; | ||
364 | } | ||
365 | |||
366 | dev_dbg(delta->dev, "%s one decoder matching %4.4s => %4.4s\n", | ||
367 | ctx->name, (char *)&streamformat, (char *)&pixelformat); | ||
368 | |||
369 | /* update instance name */ | ||
370 | snprintf(ctx->name, sizeof(ctx->name), "[%3d:%4.4s]", | ||
371 | delta->instance_id, (char *)&streamformat); | ||
372 | |||
373 | /* open decoder instance */ | ||
374 | ret = call_dec_op(dec, open, ctx); | ||
375 | if (ret) { | ||
376 | dev_err(delta->dev, "%s failed to open decoder instance (%d)\n", | ||
377 | ctx->name, ret); | ||
378 | return ret; | ||
379 | } | ||
380 | |||
381 | dev_dbg(delta->dev, "%s %s decoder opened\n", ctx->name, dec->name); | ||
382 | |||
383 | *pdec = dec; | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | /* | ||
389 | * V4L2 ioctl operations | ||
390 | */ | ||
391 | |||
392 | static int delta_querycap(struct file *file, void *priv, | ||
393 | struct v4l2_capability *cap) | ||
394 | { | ||
395 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
396 | struct delta_dev *delta = ctx->dev; | ||
397 | |||
398 | strlcpy(cap->driver, DELTA_NAME, sizeof(cap->driver)); | ||
399 | strlcpy(cap->card, delta->vdev->name, sizeof(cap->card)); | ||
400 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", | ||
401 | delta->pdev->name); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int delta_enum_fmt_stream(struct file *file, void *priv, | ||
407 | struct v4l2_fmtdesc *f) | ||
408 | { | ||
409 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
410 | struct delta_dev *delta = ctx->dev; | ||
411 | |||
412 | if (unlikely(f->index >= delta->nb_of_streamformats)) | ||
413 | return -EINVAL; | ||
414 | |||
415 | f->pixelformat = delta->streamformats[f->index]; | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int delta_enum_fmt_frame(struct file *file, void *priv, | ||
421 | struct v4l2_fmtdesc *f) | ||
422 | { | ||
423 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
424 | struct delta_dev *delta = ctx->dev; | ||
425 | |||
426 | if (unlikely(f->index >= delta->nb_of_pixelformats)) | ||
427 | return -EINVAL; | ||
428 | |||
429 | f->pixelformat = delta->pixelformats[f->index]; | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int delta_g_fmt_stream(struct file *file, void *fh, | ||
435 | struct v4l2_format *f) | ||
436 | { | ||
437 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
438 | struct delta_dev *delta = ctx->dev; | ||
439 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
440 | struct delta_streaminfo *streaminfo = &ctx->streaminfo; | ||
441 | |||
442 | if (!(ctx->flags & DELTA_FLAG_STREAMINFO)) | ||
443 | dev_dbg(delta->dev, | ||
444 | "%s V4L2 GET_FMT (OUTPUT): no stream information available, using default\n", | ||
445 | ctx->name); | ||
446 | |||
447 | pix->pixelformat = streaminfo->streamformat; | ||
448 | pix->width = streaminfo->width; | ||
449 | pix->height = streaminfo->height; | ||
450 | pix->field = streaminfo->field; | ||
451 | pix->bytesperline = 0; | ||
452 | pix->sizeimage = ctx->max_au_size; | ||
453 | pix->colorspace = streaminfo->colorspace; | ||
454 | pix->xfer_func = streaminfo->xfer_func; | ||
455 | pix->ycbcr_enc = streaminfo->ycbcr_enc; | ||
456 | pix->quantization = streaminfo->quantization; | ||
457 | |||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | static int delta_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) | ||
462 | { | ||
463 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
464 | struct delta_dev *delta = ctx->dev; | ||
465 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
466 | struct delta_frameinfo *frameinfo = &ctx->frameinfo; | ||
467 | struct delta_streaminfo *streaminfo = &ctx->streaminfo; | ||
468 | |||
469 | if (!(ctx->flags & DELTA_FLAG_FRAMEINFO)) | ||
470 | dev_dbg(delta->dev, | ||
471 | "%s V4L2 GET_FMT (CAPTURE): no frame information available, using default\n", | ||
472 | ctx->name); | ||
473 | |||
474 | pix->pixelformat = frameinfo->pixelformat; | ||
475 | pix->width = frameinfo->aligned_width; | ||
476 | pix->height = frameinfo->aligned_height; | ||
477 | pix->field = frameinfo->field; | ||
478 | pix->bytesperline = frame_stride(frameinfo->aligned_width, | ||
479 | frameinfo->pixelformat); | ||
480 | pix->sizeimage = frameinfo->size; | ||
481 | |||
482 | if (ctx->flags & DELTA_FLAG_STREAMINFO) { | ||
483 | /* align colorspace & friends on stream ones if any set */ | ||
484 | frameinfo->colorspace = streaminfo->colorspace; | ||
485 | frameinfo->xfer_func = streaminfo->xfer_func; | ||
486 | frameinfo->ycbcr_enc = streaminfo->ycbcr_enc; | ||
487 | frameinfo->quantization = streaminfo->quantization; | ||
488 | } | ||
489 | pix->colorspace = frameinfo->colorspace; | ||
490 | pix->xfer_func = frameinfo->xfer_func; | ||
491 | pix->ycbcr_enc = frameinfo->ycbcr_enc; | ||
492 | pix->quantization = frameinfo->quantization; | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int delta_try_fmt_stream(struct file *file, void *priv, | ||
498 | struct v4l2_format *f) | ||
499 | { | ||
500 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
501 | struct delta_dev *delta = ctx->dev; | ||
502 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
503 | u32 streamformat = pix->pixelformat; | ||
504 | const struct delta_dec *dec; | ||
505 | u32 width, height; | ||
506 | u32 au_size; | ||
507 | |||
508 | dec = delta_find_decoder(ctx, streamformat, ctx->frameinfo.pixelformat); | ||
509 | if (!dec) { | ||
510 | dev_dbg(delta->dev, | ||
511 | "%s V4L2 TRY_FMT (OUTPUT): unsupported format %4.4s\n", | ||
512 | ctx->name, (char *)&pix->pixelformat); | ||
513 | return -EINVAL; | ||
514 | } | ||
515 | |||
516 | /* adjust width & height */ | ||
517 | width = pix->width; | ||
518 | height = pix->height; | ||
519 | v4l_bound_align_image | ||
520 | (&pix->width, | ||
521 | DELTA_MIN_WIDTH, | ||
522 | dec->max_width ? dec->max_width : DELTA_MAX_WIDTH, | ||
523 | 0, | ||
524 | &pix->height, | ||
525 | DELTA_MIN_HEIGHT, | ||
526 | dec->max_height ? dec->max_height : DELTA_MAX_HEIGHT, | ||
527 | 0, 0); | ||
528 | |||
529 | if ((pix->width != width) || (pix->height != height)) | ||
530 | dev_dbg(delta->dev, | ||
531 | "%s V4L2 TRY_FMT (OUTPUT): resolution updated %dx%d -> %dx%d to fit min/max/alignment\n", | ||
532 | ctx->name, width, height, | ||
533 | pix->width, pix->height); | ||
534 | |||
535 | au_size = estimated_au_size(pix->width, pix->height); | ||
536 | if (pix->sizeimage < au_size) { | ||
537 | dev_dbg(delta->dev, | ||
538 | "%s V4L2 TRY_FMT (OUTPUT): size updated %d -> %d to fit estimated size\n", | ||
539 | ctx->name, pix->sizeimage, au_size); | ||
540 | pix->sizeimage = au_size; | ||
541 | } | ||
542 | |||
543 | pix->bytesperline = 0; | ||
544 | |||
545 | if (pix->field == V4L2_FIELD_ANY) | ||
546 | pix->field = V4L2_FIELD_NONE; | ||
547 | |||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int delta_try_fmt_frame(struct file *file, void *priv, | ||
552 | struct v4l2_format *f) | ||
553 | { | ||
554 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
555 | struct delta_dev *delta = ctx->dev; | ||
556 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
557 | u32 pixelformat = pix->pixelformat; | ||
558 | const struct delta_dec *dec; | ||
559 | u32 width, height; | ||
560 | |||
561 | dec = delta_find_decoder(ctx, ctx->streaminfo.streamformat, | ||
562 | pixelformat); | ||
563 | if (!dec) { | ||
564 | dev_dbg(delta->dev, | ||
565 | "%s V4L2 TRY_FMT (CAPTURE): unsupported format %4.4s\n", | ||
566 | ctx->name, (char *)&pixelformat); | ||
567 | return -EINVAL; | ||
568 | } | ||
569 | |||
570 | /* adjust width & height */ | ||
571 | width = pix->width; | ||
572 | height = pix->height; | ||
573 | v4l_bound_align_image(&pix->width, | ||
574 | DELTA_MIN_WIDTH, DELTA_MAX_WIDTH, | ||
575 | frame_alignment(pixelformat) - 1, | ||
576 | &pix->height, | ||
577 | DELTA_MIN_HEIGHT, DELTA_MAX_HEIGHT, | ||
578 | frame_alignment(pixelformat) - 1, 0); | ||
579 | |||
580 | if ((pix->width != width) || (pix->height != height)) | ||
581 | dev_dbg(delta->dev, | ||
582 | "%s V4L2 TRY_FMT (CAPTURE): resolution updated %dx%d -> %dx%d to fit min/max/alignment\n", | ||
583 | ctx->name, width, height, pix->width, pix->height); | ||
584 | |||
585 | /* default decoder alignment constraint */ | ||
586 | width = ALIGN(pix->width, DELTA_WIDTH_ALIGNMENT); | ||
587 | height = ALIGN(pix->height, DELTA_HEIGHT_ALIGNMENT); | ||
588 | if ((pix->width != width) || (pix->height != height)) | ||
589 | dev_dbg(delta->dev, | ||
590 | "%s V4L2 TRY_FMT (CAPTURE): resolution updated %dx%d -> %dx%d to fit decoder alignment\n", | ||
591 | ctx->name, width, height, pix->width, pix->height); | ||
592 | |||
593 | if (!pix->colorspace) { | ||
594 | pix->colorspace = V4L2_COLORSPACE_REC709; | ||
595 | pix->xfer_func = V4L2_XFER_FUNC_DEFAULT; | ||
596 | pix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | ||
597 | pix->quantization = V4L2_QUANTIZATION_DEFAULT; | ||
598 | } | ||
599 | |||
600 | pix->width = width; | ||
601 | pix->height = height; | ||
602 | pix->bytesperline = frame_stride(pix->width, pixelformat); | ||
603 | pix->sizeimage = frame_size(pix->width, pix->height, pixelformat); | ||
604 | |||
605 | if (pix->field == V4L2_FIELD_ANY) | ||
606 | pix->field = V4L2_FIELD_NONE; | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static int delta_s_fmt_stream(struct file *file, void *fh, | ||
612 | struct v4l2_format *f) | ||
613 | { | ||
614 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
615 | struct delta_dev *delta = ctx->dev; | ||
616 | struct vb2_queue *vq; | ||
617 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
618 | int ret; | ||
619 | |||
620 | ret = delta_try_fmt_stream(file, fh, f); | ||
621 | if (ret) { | ||
622 | dev_dbg(delta->dev, | ||
623 | "%s V4L2 S_FMT (OUTPUT): unsupported format %4.4s\n", | ||
624 | ctx->name, (char *)&pix->pixelformat); | ||
625 | return ret; | ||
626 | } | ||
627 | |||
628 | vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); | ||
629 | if (vb2_is_streaming(vq)) { | ||
630 | dev_dbg(delta->dev, "%s V4L2 S_FMT (OUTPUT): queue busy\n", | ||
631 | ctx->name); | ||
632 | return -EBUSY; | ||
633 | } | ||
634 | |||
635 | ctx->max_au_size = pix->sizeimage; | ||
636 | ctx->streaminfo.width = pix->width; | ||
637 | ctx->streaminfo.height = pix->height; | ||
638 | ctx->streaminfo.streamformat = pix->pixelformat; | ||
639 | ctx->streaminfo.colorspace = pix->colorspace; | ||
640 | ctx->streaminfo.xfer_func = pix->xfer_func; | ||
641 | ctx->streaminfo.ycbcr_enc = pix->ycbcr_enc; | ||
642 | ctx->streaminfo.quantization = pix->quantization; | ||
643 | ctx->flags |= DELTA_FLAG_STREAMINFO; | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | static int delta_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) | ||
649 | { | ||
650 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
651 | struct delta_dev *delta = ctx->dev; | ||
652 | const struct delta_dec *dec = ctx->dec; | ||
653 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
654 | struct delta_frameinfo frameinfo; | ||
655 | struct vb2_queue *vq; | ||
656 | int ret; | ||
657 | |||
658 | vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); | ||
659 | if (vb2_is_streaming(vq)) { | ||
660 | dev_dbg(delta->dev, "%s V4L2 S_FMT (CAPTURE): queue busy\n", | ||
661 | ctx->name); | ||
662 | return -EBUSY; | ||
663 | } | ||
664 | |||
665 | if (ctx->state < DELTA_STATE_READY) { | ||
666 | /* | ||
667 | * decoder not yet opened and valid stream header not found, | ||
668 | * could not negotiate format with decoder, check at least | ||
669 | * pixel format & negotiate resolution boundaries | ||
670 | * and alignment... | ||
671 | */ | ||
672 | ret = delta_try_fmt_frame(file, fh, f); | ||
673 | if (ret) { | ||
674 | dev_dbg(delta->dev, | ||
675 | "%s V4L2 S_FMT (CAPTURE): unsupported format %4.4s\n", | ||
676 | ctx->name, (char *)&pix->pixelformat); | ||
677 | return ret; | ||
678 | } | ||
679 | |||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | /* set frame information to decoder */ | ||
684 | memset(&frameinfo, 0, sizeof(frameinfo)); | ||
685 | frameinfo.pixelformat = pix->pixelformat; | ||
686 | frameinfo.width = pix->width; | ||
687 | frameinfo.height = pix->height; | ||
688 | frameinfo.aligned_width = pix->width; | ||
689 | frameinfo.aligned_height = pix->height; | ||
690 | frameinfo.size = pix->sizeimage; | ||
691 | frameinfo.field = pix->field; | ||
692 | frameinfo.colorspace = pix->colorspace; | ||
693 | frameinfo.xfer_func = pix->xfer_func; | ||
694 | frameinfo.ycbcr_enc = pix->ycbcr_enc; | ||
695 | frameinfo.quantization = pix->quantization; | ||
696 | ret = call_dec_op(dec, set_frameinfo, ctx, &frameinfo); | ||
697 | if (ret) | ||
698 | return ret; | ||
699 | |||
700 | /* then get what decoder can really do */ | ||
701 | ret = call_dec_op(dec, get_frameinfo, ctx, &frameinfo); | ||
702 | if (ret) | ||
703 | return ret; | ||
704 | |||
705 | ctx->flags |= DELTA_FLAG_FRAMEINFO; | ||
706 | ctx->frameinfo = frameinfo; | ||
707 | |||
708 | pix->pixelformat = frameinfo.pixelformat; | ||
709 | pix->width = frameinfo.aligned_width; | ||
710 | pix->height = frameinfo.aligned_height; | ||
711 | pix->bytesperline = frame_stride(pix->width, pix->pixelformat); | ||
712 | pix->sizeimage = frameinfo.size; | ||
713 | pix->field = frameinfo.field; | ||
714 | pix->colorspace = frameinfo.colorspace; | ||
715 | pix->xfer_func = frameinfo.xfer_func; | ||
716 | pix->ycbcr_enc = frameinfo.ycbcr_enc; | ||
717 | pix->quantization = frameinfo.quantization; | ||
718 | |||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | static int delta_g_selection(struct file *file, void *fh, | ||
723 | struct v4l2_selection *s) | ||
724 | { | ||
725 | struct delta_ctx *ctx = to_ctx(fh); | ||
726 | struct delta_frameinfo *frameinfo = &ctx->frameinfo; | ||
727 | struct v4l2_rect crop; | ||
728 | |||
729 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
730 | return -EINVAL; | ||
731 | |||
732 | if ((ctx->flags & DELTA_FLAG_FRAMEINFO) && | ||
733 | (frameinfo->flags & DELTA_FRAMEINFO_FLAG_CROP)) { | ||
734 | crop = frameinfo->crop; | ||
735 | } else { | ||
736 | /* default to video dimensions */ | ||
737 | crop.left = 0; | ||
738 | crop.top = 0; | ||
739 | crop.width = frameinfo->width; | ||
740 | crop.height = frameinfo->height; | ||
741 | } | ||
742 | |||
743 | switch (s->target) { | ||
744 | case V4L2_SEL_TGT_COMPOSE: | ||
745 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
746 | /* visible area inside video */ | ||
747 | s->r = crop; | ||
748 | break; | ||
749 | case V4L2_SEL_TGT_COMPOSE_PADDED: | ||
750 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
751 | /* up to aligned dimensions */ | ||
752 | s->r.left = 0; | ||
753 | s->r.top = 0; | ||
754 | s->r.width = frameinfo->aligned_width; | ||
755 | s->r.height = frameinfo->aligned_height; | ||
756 | break; | ||
757 | default: | ||
758 | return -EINVAL; | ||
759 | } | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | /* v4l2 ioctl ops */ | ||
765 | static const struct v4l2_ioctl_ops delta_ioctl_ops = { | ||
766 | .vidioc_querycap = delta_querycap, | ||
767 | .vidioc_enum_fmt_vid_cap = delta_enum_fmt_frame, | ||
768 | .vidioc_g_fmt_vid_cap = delta_g_fmt_frame, | ||
769 | .vidioc_try_fmt_vid_cap = delta_try_fmt_frame, | ||
770 | .vidioc_s_fmt_vid_cap = delta_s_fmt_frame, | ||
771 | .vidioc_enum_fmt_vid_out = delta_enum_fmt_stream, | ||
772 | .vidioc_g_fmt_vid_out = delta_g_fmt_stream, | ||
773 | .vidioc_try_fmt_vid_out = delta_try_fmt_stream, | ||
774 | .vidioc_s_fmt_vid_out = delta_s_fmt_stream, | ||
775 | .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, | ||
776 | .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, | ||
777 | .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, | ||
778 | .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, | ||
779 | .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, | ||
780 | .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, | ||
781 | .vidioc_streamon = v4l2_m2m_ioctl_streamon, | ||
782 | .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, | ||
783 | .vidioc_g_selection = delta_g_selection, | ||
784 | }; | ||
785 | |||
786 | /* | ||
787 | * mem-to-mem operations | ||
788 | */ | ||
789 | |||
790 | static void delta_run_work(struct work_struct *work) | ||
791 | { | ||
792 | struct delta_ctx *ctx = container_of(work, struct delta_ctx, run_work); | ||
793 | struct delta_dev *delta = ctx->dev; | ||
794 | const struct delta_dec *dec = ctx->dec; | ||
795 | struct delta_au *au; | ||
796 | struct delta_frame *frame = NULL; | ||
797 | int ret = 0; | ||
798 | bool discard = false; | ||
799 | struct vb2_v4l2_buffer *vbuf; | ||
800 | |||
801 | if (!dec) { | ||
802 | dev_err(delta->dev, "%s no decoder opened yet\n", ctx->name); | ||
803 | return; | ||
804 | } | ||
805 | |||
806 | /* protect instance against reentrancy */ | ||
807 | mutex_lock(&ctx->lock); | ||
808 | |||
809 | vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); | ||
810 | if (!vbuf) { | ||
811 | dev_err(delta->dev, "%s no buffer to decode\n", ctx->name); | ||
812 | mutex_unlock(&ctx->lock); | ||
813 | return; | ||
814 | } | ||
815 | au = to_au(vbuf); | ||
816 | au->size = vb2_get_plane_payload(&vbuf->vb2_buf, 0); | ||
817 | au->dts = vbuf->vb2_buf.timestamp; | ||
818 | |||
819 | /* dump access unit */ | ||
820 | dump_au(ctx, au); | ||
821 | |||
822 | /* enable the hardware */ | ||
823 | if (!dec->pm) { | ||
824 | ret = delta_get_sync(ctx); | ||
825 | if (ret) | ||
826 | goto err; | ||
827 | } | ||
828 | |||
829 | /* decode this access unit */ | ||
830 | ret = call_dec_op(dec, decode, ctx, au); | ||
831 | |||
832 | /* | ||
833 | * if the (-ENODATA) value is returned, it refers to the interlaced | ||
834 | * stream case for which 2 access units are needed to get 1 frame. | ||
835 | * So, this returned value doesn't mean that the decoding fails, but | ||
836 | * indicates that the timestamp information of the access unit shall | ||
837 | * not be taken into account, and that the V4L2 buffer associated with | ||
838 | * the access unit shall be flagged with V4L2_BUF_FLAG_ERROR to inform | ||
839 | * the user of this situation | ||
840 | */ | ||
841 | if (ret == -ENODATA) { | ||
842 | discard = true; | ||
843 | } else if (ret) { | ||
844 | dev_err(delta->dev, "%s decoding failed (%d)\n", | ||
845 | ctx->name, ret); | ||
846 | |||
847 | /* disable the hardware */ | ||
848 | if (!dec->pm) | ||
849 | delta_put_autosuspend(ctx); | ||
850 | |||
851 | goto err; | ||
852 | } | ||
853 | |||
854 | /* disable the hardware */ | ||
855 | if (!dec->pm) | ||
856 | delta_put_autosuspend(ctx); | ||
857 | |||
858 | /* push au timestamp in FIFO */ | ||
859 | if (!discard) | ||
860 | delta_push_dts(ctx, au->dts); | ||
861 | |||
862 | /* get available decoded frames */ | ||
863 | while (1) { | ||
864 | ret = call_dec_op(dec, get_frame, ctx, &frame); | ||
865 | if (ret == -ENODATA) { | ||
866 | /* no more decoded frames */ | ||
867 | goto out; | ||
868 | } | ||
869 | if (ret) { | ||
870 | dev_err(delta->dev, "%s cannot get decoded frame (%d)\n", | ||
871 | ctx->name, ret); | ||
872 | goto out; | ||
873 | } | ||
874 | if (!frame) { | ||
875 | dev_err(delta->dev, | ||
876 | "%s NULL decoded frame\n", | ||
877 | ctx->name); | ||
878 | ret = -EIO; | ||
879 | goto out; | ||
880 | } | ||
881 | |||
882 | /* pop timestamp and mark frame with it */ | ||
883 | delta_pop_dts(ctx, &frame->dts); | ||
884 | |||
885 | /* release decoded frame to user */ | ||
886 | delta_frame_done(ctx, frame, 0); | ||
887 | } | ||
888 | |||
889 | out: | ||
890 | requeue_free_frames(ctx); | ||
891 | delta_au_done(ctx, au, (discard ? -ENODATA : 0)); | ||
892 | mutex_unlock(&ctx->lock); | ||
893 | v4l2_m2m_job_finish(delta->m2m_dev, ctx->fh.m2m_ctx); | ||
894 | return; | ||
895 | |||
896 | err: | ||
897 | requeue_free_frames(ctx); | ||
898 | delta_au_done(ctx, au, ret); | ||
899 | mutex_unlock(&ctx->lock); | ||
900 | v4l2_m2m_job_finish(delta->m2m_dev, ctx->fh.m2m_ctx); | ||
901 | } | ||
902 | |||
903 | static void delta_device_run(void *priv) | ||
904 | { | ||
905 | struct delta_ctx *ctx = priv; | ||
906 | struct delta_dev *delta = ctx->dev; | ||
907 | |||
908 | queue_work(delta->work_queue, &ctx->run_work); | ||
909 | } | ||
910 | |||
911 | static void delta_job_abort(void *priv) | ||
912 | { | ||
913 | struct delta_ctx *ctx = priv; | ||
914 | struct delta_dev *delta = ctx->dev; | ||
915 | |||
916 | dev_dbg(delta->dev, "%s aborting job\n", ctx->name); | ||
917 | |||
918 | ctx->aborting = true; | ||
919 | } | ||
920 | |||
921 | static int delta_job_ready(void *priv) | ||
922 | { | ||
923 | struct delta_ctx *ctx = priv; | ||
924 | struct delta_dev *delta = ctx->dev; | ||
925 | int src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx); | ||
926 | |||
927 | if (!src_bufs) { | ||
928 | dev_dbg(delta->dev, "%s not ready: not enough video buffers.\n", | ||
929 | ctx->name); | ||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) { | ||
934 | dev_dbg(delta->dev, "%s not ready: not enough video capture buffers.\n", | ||
935 | ctx->name); | ||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | if (ctx->aborting) { | ||
940 | dev_dbg(delta->dev, "%s job not ready: aborting\n", ctx->name); | ||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | dev_dbg(delta->dev, "%s job ready\n", ctx->name); | ||
945 | |||
946 | return 1; | ||
947 | } | ||
948 | |||
949 | /* mem-to-mem ops */ | ||
950 | static struct v4l2_m2m_ops delta_m2m_ops = { | ||
951 | .device_run = delta_device_run, | ||
952 | .job_ready = delta_job_ready, | ||
953 | .job_abort = delta_job_abort, | ||
954 | .lock = delta_lock, | ||
955 | .unlock = delta_unlock, | ||
956 | }; | ||
957 | |||
958 | /* | ||
959 | * VB2 queue operations | ||
960 | */ | ||
961 | |||
962 | static int delta_vb2_au_queue_setup(struct vb2_queue *vq, | ||
963 | unsigned int *num_buffers, | ||
964 | unsigned int *num_planes, | ||
965 | unsigned int sizes[], | ||
966 | struct device *alloc_devs[]) | ||
967 | { | ||
968 | struct delta_ctx *ctx = vb2_get_drv_priv(vq); | ||
969 | unsigned int size = ctx->max_au_size; | ||
970 | |||
971 | if (*num_planes) | ||
972 | return sizes[0] < size ? -EINVAL : 0; | ||
973 | |||
974 | *num_planes = 1; | ||
975 | if (*num_buffers < 1) | ||
976 | *num_buffers = 1; | ||
977 | if (*num_buffers > DELTA_MAX_AUS) | ||
978 | *num_buffers = DELTA_MAX_AUS; | ||
979 | |||
980 | sizes[0] = size; | ||
981 | |||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | static int delta_vb2_au_prepare(struct vb2_buffer *vb) | ||
986 | { | ||
987 | struct vb2_queue *q = vb->vb2_queue; | ||
988 | struct delta_ctx *ctx = vb2_get_drv_priv(q); | ||
989 | struct delta_dev *delta = ctx->dev; | ||
990 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | ||
991 | struct delta_au *au = to_au(vbuf); | ||
992 | |||
993 | if (!au->prepared) { | ||
994 | /* get memory addresses */ | ||
995 | au->vaddr = vb2_plane_vaddr(&au->vbuf.vb2_buf, 0); | ||
996 | au->paddr = vb2_dma_contig_plane_dma_addr | ||
997 | (&au->vbuf.vb2_buf, 0); | ||
998 | au->prepared = true; | ||
999 | dev_dbg(delta->dev, "%s au[%d] prepared; virt=0x%p, phy=0x%pad\n", | ||
1000 | ctx->name, vb->index, au->vaddr, &au->paddr); | ||
1001 | } | ||
1002 | |||
1003 | if (vbuf->field == V4L2_FIELD_ANY) | ||
1004 | vbuf->field = V4L2_FIELD_NONE; | ||
1005 | |||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static int delta_setup_frame(struct delta_ctx *ctx, | ||
1010 | struct delta_frame *frame) | ||
1011 | { | ||
1012 | struct delta_dev *delta = ctx->dev; | ||
1013 | const struct delta_dec *dec = ctx->dec; | ||
1014 | |||
1015 | if (frame->index >= DELTA_MAX_FRAMES) { | ||
1016 | dev_err(delta->dev, | ||
1017 | "%s frame index=%d exceeds output frame count (%d)\n", | ||
1018 | ctx->name, frame->index, DELTA_MAX_FRAMES); | ||
1019 | return -EINVAL; | ||
1020 | } | ||
1021 | |||
1022 | if (ctx->nb_of_frames >= DELTA_MAX_FRAMES) { | ||
1023 | dev_err(delta->dev, | ||
1024 | "%s number of frames exceeds output frame count (%d > %d)\n", | ||
1025 | ctx->name, ctx->nb_of_frames, DELTA_MAX_FRAMES); | ||
1026 | return -EINVAL; | ||
1027 | } | ||
1028 | |||
1029 | if (frame->index != ctx->nb_of_frames) { | ||
1030 | dev_warn(delta->dev, | ||
1031 | "%s frame index discontinuity detected, expected %d, got %d\n", | ||
1032 | ctx->name, ctx->nb_of_frames, frame->index); | ||
1033 | } | ||
1034 | |||
1035 | frame->state = DELTA_FRAME_FREE; | ||
1036 | ctx->frames[ctx->nb_of_frames] = frame; | ||
1037 | ctx->nb_of_frames++; | ||
1038 | |||
1039 | /* setup frame on decoder side */ | ||
1040 | return call_dec_op(dec, setup_frame, ctx, frame); | ||
1041 | } | ||
1042 | |||
1043 | /* | ||
1044 | * default implementation of get_frameinfo decoder ops | ||
1045 | * matching frame information from stream information | ||
1046 | * & with default pixel format & default alignment. | ||
1047 | */ | ||
1048 | int delta_get_frameinfo_default(struct delta_ctx *ctx, | ||
1049 | struct delta_frameinfo *frameinfo) | ||
1050 | { | ||
1051 | struct delta_streaminfo *streaminfo = &ctx->streaminfo; | ||
1052 | |||
1053 | memset(frameinfo, 0, sizeof(*frameinfo)); | ||
1054 | frameinfo->pixelformat = V4L2_PIX_FMT_NV12; | ||
1055 | frameinfo->width = streaminfo->width; | ||
1056 | frameinfo->height = streaminfo->height; | ||
1057 | frameinfo->aligned_width = ALIGN(streaminfo->width, | ||
1058 | DELTA_WIDTH_ALIGNMENT); | ||
1059 | frameinfo->aligned_height = ALIGN(streaminfo->height, | ||
1060 | DELTA_HEIGHT_ALIGNMENT); | ||
1061 | frameinfo->size = frame_size(frameinfo->aligned_width, | ||
1062 | frameinfo->aligned_height, | ||
1063 | frameinfo->pixelformat); | ||
1064 | if (streaminfo->flags & DELTA_STREAMINFO_FLAG_CROP) { | ||
1065 | frameinfo->flags |= DELTA_FRAMEINFO_FLAG_CROP; | ||
1066 | frameinfo->crop = streaminfo->crop; | ||
1067 | } | ||
1068 | if (streaminfo->flags & DELTA_STREAMINFO_FLAG_PIXELASPECT) { | ||
1069 | frameinfo->flags |= DELTA_FRAMEINFO_FLAG_PIXELASPECT; | ||
1070 | frameinfo->pixelaspect = streaminfo->pixelaspect; | ||
1071 | } | ||
1072 | frameinfo->field = streaminfo->field; | ||
1073 | |||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | /* | ||
1078 | * default implementation of recycle decoder ops | ||
1079 | * consisting to relax the "decoded" frame state | ||
1080 | */ | ||
1081 | int delta_recycle_default(struct delta_ctx *pctx, | ||
1082 | struct delta_frame *frame) | ||
1083 | { | ||
1084 | frame->state &= ~DELTA_FRAME_DEC; | ||
1085 | |||
1086 | return 0; | ||
1087 | } | ||
1088 | |||
1089 | static void dump_frames_status(struct delta_ctx *ctx) | ||
1090 | { | ||
1091 | struct delta_dev *delta = ctx->dev; | ||
1092 | unsigned int i; | ||
1093 | struct delta_frame *frame; | ||
1094 | unsigned char str[100] = ""; | ||
1095 | |||
1096 | dev_info(delta->dev, | ||
1097 | "%s dumping frames status...\n", ctx->name); | ||
1098 | |||
1099 | for (i = 0; i < ctx->nb_of_frames; i++) { | ||
1100 | frame = ctx->frames[i]; | ||
1101 | dev_info(delta->dev, | ||
1102 | "%s frame[%d] %s\n", | ||
1103 | ctx->name, frame->index, | ||
1104 | frame_state_str(frame->state, | ||
1105 | str, sizeof(str))); | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | int delta_get_free_frame(struct delta_ctx *ctx, | ||
1110 | struct delta_frame **pframe) | ||
1111 | { | ||
1112 | struct delta_dev *delta = ctx->dev; | ||
1113 | struct vb2_v4l2_buffer *vbuf; | ||
1114 | struct delta_frame *frame; | ||
1115 | |||
1116 | *pframe = NULL; | ||
1117 | |||
1118 | vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); | ||
1119 | if (!vbuf) { | ||
1120 | dev_err(delta->dev, "%s no frame available", | ||
1121 | ctx->name); | ||
1122 | return -EIO; | ||
1123 | } | ||
1124 | |||
1125 | frame = to_frame(vbuf); | ||
1126 | frame->state &= ~DELTA_FRAME_M2M; | ||
1127 | if (frame->state != DELTA_FRAME_FREE) { | ||
1128 | dev_err(delta->dev, | ||
1129 | "%s frame[%d] is not free\n", | ||
1130 | ctx->name, frame->index); | ||
1131 | dump_frames_status(ctx); | ||
1132 | return -ENODATA; | ||
1133 | } | ||
1134 | |||
1135 | dev_dbg(delta->dev, | ||
1136 | "%s get free frame[%d]\n", ctx->name, frame->index); | ||
1137 | |||
1138 | *pframe = frame; | ||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1142 | int delta_get_sync(struct delta_ctx *ctx) | ||
1143 | { | ||
1144 | struct delta_dev *delta = ctx->dev; | ||
1145 | int ret = 0; | ||
1146 | |||
1147 | /* enable the hardware */ | ||
1148 | ret = pm_runtime_get_sync(delta->dev); | ||
1149 | if (ret < 0) { | ||
1150 | dev_err(delta->dev, "%s pm_runtime_get_sync failed (%d)\n", | ||
1151 | __func__, ret); | ||
1152 | return ret; | ||
1153 | } | ||
1154 | |||
1155 | return 0; | ||
1156 | } | ||
1157 | |||
1158 | void delta_put_autosuspend(struct delta_ctx *ctx) | ||
1159 | { | ||
1160 | struct delta_dev *delta = ctx->dev; | ||
1161 | |||
1162 | pm_runtime_put_autosuspend(delta->dev); | ||
1163 | } | ||
1164 | |||
1165 | static void delta_vb2_au_queue(struct vb2_buffer *vb) | ||
1166 | { | ||
1167 | struct vb2_queue *q = vb->vb2_queue; | ||
1168 | struct delta_ctx *ctx = vb2_get_drv_priv(q); | ||
1169 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | ||
1170 | |||
1171 | v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); | ||
1172 | } | ||
1173 | |||
1174 | static int delta_vb2_au_start_streaming(struct vb2_queue *q, | ||
1175 | unsigned int count) | ||
1176 | { | ||
1177 | struct delta_ctx *ctx = vb2_get_drv_priv(q); | ||
1178 | struct delta_dev *delta = ctx->dev; | ||
1179 | const struct delta_dec *dec = ctx->dec; | ||
1180 | struct delta_au *au; | ||
1181 | int ret = 0; | ||
1182 | struct vb2_v4l2_buffer *vbuf = NULL; | ||
1183 | struct delta_streaminfo *streaminfo = &ctx->streaminfo; | ||
1184 | struct delta_frameinfo *frameinfo = &ctx->frameinfo; | ||
1185 | |||
1186 | if ((ctx->state != DELTA_STATE_WF_FORMAT) && | ||
1187 | (ctx->state != DELTA_STATE_WF_STREAMINFO)) | ||
1188 | return 0; | ||
1189 | |||
1190 | if (ctx->state == DELTA_STATE_WF_FORMAT) { | ||
1191 | /* open decoder if not yet done */ | ||
1192 | ret = delta_open_decoder(ctx, | ||
1193 | ctx->streaminfo.streamformat, | ||
1194 | ctx->frameinfo.pixelformat, &dec); | ||
1195 | if (ret) | ||
1196 | goto err; | ||
1197 | ctx->dec = dec; | ||
1198 | ctx->state = DELTA_STATE_WF_STREAMINFO; | ||
1199 | } | ||
1200 | |||
1201 | /* | ||
1202 | * first buffer should contain stream header, | ||
1203 | * decode it to get the infos related to stream | ||
1204 | * such as width, height, dpb, ... | ||
1205 | */ | ||
1206 | vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); | ||
1207 | if (!vbuf) { | ||
1208 | dev_err(delta->dev, "%s failed to start streaming, no stream header buffer enqueued\n", | ||
1209 | ctx->name); | ||
1210 | ret = -EINVAL; | ||
1211 | goto err; | ||
1212 | } | ||
1213 | au = to_au(vbuf); | ||
1214 | au->size = vb2_get_plane_payload(&vbuf->vb2_buf, 0); | ||
1215 | au->dts = vbuf->vb2_buf.timestamp; | ||
1216 | |||
1217 | delta_push_dts(ctx, au->dts); | ||
1218 | |||
1219 | /* dump access unit */ | ||
1220 | dump_au(ctx, au); | ||
1221 | |||
1222 | /* decode this access unit */ | ||
1223 | ret = call_dec_op(dec, decode, ctx, au); | ||
1224 | if (ret) { | ||
1225 | dev_err(delta->dev, "%s failed to start streaming, header decoding failed (%d)\n", | ||
1226 | ctx->name, ret); | ||
1227 | goto err; | ||
1228 | } | ||
1229 | |||
1230 | ret = call_dec_op(dec, get_streaminfo, ctx, streaminfo); | ||
1231 | if (ret) { | ||
1232 | dev_dbg_ratelimited(delta->dev, | ||
1233 | "%s failed to start streaming, valid stream header not yet decoded\n", | ||
1234 | ctx->name); | ||
1235 | goto err; | ||
1236 | } | ||
1237 | ctx->flags |= DELTA_FLAG_STREAMINFO; | ||
1238 | |||
1239 | ret = call_dec_op(dec, get_frameinfo, ctx, frameinfo); | ||
1240 | if (ret) | ||
1241 | goto err; | ||
1242 | ctx->flags |= DELTA_FLAG_FRAMEINFO; | ||
1243 | |||
1244 | ctx->state = DELTA_STATE_READY; | ||
1245 | |||
1246 | delta_au_done(ctx, au, ret); | ||
1247 | return 0; | ||
1248 | |||
1249 | err: | ||
1250 | /* | ||
1251 | * return all buffers to vb2 in QUEUED state. | ||
1252 | * This will give ownership back to userspace | ||
1253 | */ | ||
1254 | if (vbuf) | ||
1255 | v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED); | ||
1256 | |||
1257 | while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) | ||
1258 | v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | static void delta_vb2_au_stop_streaming(struct vb2_queue *q) | ||
1263 | { | ||
1264 | struct delta_ctx *ctx = vb2_get_drv_priv(q); | ||
1265 | struct vb2_v4l2_buffer *vbuf; | ||
1266 | |||
1267 | delta_flush_dts(ctx); | ||
1268 | |||
1269 | /* return all buffers to vb2 in ERROR state */ | ||
1270 | while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) | ||
1271 | v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); | ||
1272 | |||
1273 | ctx->au_num = 0; | ||
1274 | |||
1275 | ctx->aborting = false; | ||
1276 | } | ||
1277 | |||
1278 | static int delta_vb2_frame_queue_setup(struct vb2_queue *vq, | ||
1279 | unsigned int *num_buffers, | ||
1280 | unsigned int *num_planes, | ||
1281 | unsigned int sizes[], | ||
1282 | struct device *alloc_devs[]) | ||
1283 | { | ||
1284 | struct delta_ctx *ctx = vb2_get_drv_priv(vq); | ||
1285 | struct delta_dev *delta = ctx->dev; | ||
1286 | struct delta_streaminfo *streaminfo = &ctx->streaminfo; | ||
1287 | struct delta_frameinfo *frameinfo = &ctx->frameinfo; | ||
1288 | unsigned int size = frameinfo->size; | ||
1289 | |||
1290 | /* | ||
1291 | * the number of output buffers needed for decoding = | ||
1292 | * user need (*num_buffers given, usually for display pipeline) + | ||
1293 | * stream need (streaminfo->dpb) + | ||
1294 | * decoding peak smoothing (depends on DELTA IP perf) | ||
1295 | */ | ||
1296 | if (*num_buffers < DELTA_MIN_FRAME_USER) { | ||
1297 | dev_dbg(delta->dev, | ||
1298 | "%s num_buffers too low (%d), increasing to %d\n", | ||
1299 | ctx->name, *num_buffers, DELTA_MIN_FRAME_USER); | ||
1300 | *num_buffers = DELTA_MIN_FRAME_USER; | ||
1301 | } | ||
1302 | |||
1303 | *num_buffers += streaminfo->dpb + DELTA_PEAK_FRAME_SMOOTHING; | ||
1304 | |||
1305 | if (*num_buffers > DELTA_MAX_FRAMES) { | ||
1306 | dev_dbg(delta->dev, | ||
1307 | "%s output frame count too high (%d), cut to %d\n", | ||
1308 | ctx->name, *num_buffers, DELTA_MAX_FRAMES); | ||
1309 | *num_buffers = DELTA_MAX_FRAMES; | ||
1310 | } | ||
1311 | |||
1312 | if (*num_planes) | ||
1313 | return sizes[0] < size ? -EINVAL : 0; | ||
1314 | |||
1315 | /* single plane for Y and CbCr */ | ||
1316 | *num_planes = 1; | ||
1317 | |||
1318 | sizes[0] = size; | ||
1319 | |||
1320 | ctx->nb_of_frames = 0; | ||
1321 | |||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | static int delta_vb2_frame_prepare(struct vb2_buffer *vb) | ||
1326 | { | ||
1327 | struct vb2_queue *q = vb->vb2_queue; | ||
1328 | struct delta_ctx *ctx = vb2_get_drv_priv(q); | ||
1329 | struct delta_dev *delta = ctx->dev; | ||
1330 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | ||
1331 | struct delta_frame *frame = to_frame(vbuf); | ||
1332 | int ret = 0; | ||
1333 | |||
1334 | if (!frame->prepared) { | ||
1335 | frame->index = vbuf->vb2_buf.index; | ||
1336 | frame->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); | ||
1337 | frame->paddr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); | ||
1338 | frame->info = ctx->frameinfo; | ||
1339 | |||
1340 | ret = delta_setup_frame(ctx, frame); | ||
1341 | if (ret) { | ||
1342 | dev_err(delta->dev, | ||
1343 | "%s setup_frame() failed (%d)\n", | ||
1344 | ctx->name, ret); | ||
1345 | return ret; | ||
1346 | } | ||
1347 | frame->prepared = true; | ||
1348 | dev_dbg(delta->dev, | ||
1349 | "%s frame[%d] prepared; virt=0x%p, phy=0x%pad\n", | ||
1350 | ctx->name, vb->index, frame->vaddr, | ||
1351 | &frame->paddr); | ||
1352 | } | ||
1353 | |||
1354 | frame->flags = vbuf->flags; | ||
1355 | |||
1356 | return 0; | ||
1357 | } | ||
1358 | |||
1359 | static void delta_vb2_frame_finish(struct vb2_buffer *vb) | ||
1360 | { | ||
1361 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | ||
1362 | struct delta_frame *frame = to_frame(vbuf); | ||
1363 | |||
1364 | /* update V4L2 fields for user */ | ||
1365 | vb2_set_plane_payload(&vbuf->vb2_buf, 0, frame->info.size); | ||
1366 | vb->timestamp = frame->dts; | ||
1367 | vbuf->field = frame->field; | ||
1368 | vbuf->flags = frame->flags; | ||
1369 | } | ||
1370 | |||
1371 | static void delta_vb2_frame_queue(struct vb2_buffer *vb) | ||
1372 | { | ||
1373 | struct vb2_queue *q = vb->vb2_queue; | ||
1374 | struct delta_ctx *ctx = vb2_get_drv_priv(q); | ||
1375 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | ||
1376 | struct delta_frame *frame = to_frame(vbuf); | ||
1377 | |||
1378 | /* recycle this frame */ | ||
1379 | delta_recycle(ctx, frame); | ||
1380 | } | ||
1381 | |||
1382 | static void delta_vb2_frame_stop_streaming(struct vb2_queue *q) | ||
1383 | { | ||
1384 | struct delta_ctx *ctx = vb2_get_drv_priv(q); | ||
1385 | struct vb2_v4l2_buffer *vbuf; | ||
1386 | struct delta_frame *frame; | ||
1387 | const struct delta_dec *dec = ctx->dec; | ||
1388 | unsigned int i; | ||
1389 | |||
1390 | delta_flush_dts(ctx); | ||
1391 | |||
1392 | call_dec_op(dec, flush, ctx); | ||
1393 | |||
1394 | /* | ||
1395 | * return all buffers to vb2 in ERROR state | ||
1396 | * & reset each frame state to OUT | ||
1397 | */ | ||
1398 | for (i = 0; i < ctx->nb_of_frames; i++) { | ||
1399 | frame = ctx->frames[i]; | ||
1400 | if (!(frame->state & DELTA_FRAME_OUT)) { | ||
1401 | vbuf = &frame->vbuf; | ||
1402 | v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); | ||
1403 | } | ||
1404 | frame->state = DELTA_FRAME_OUT; | ||
1405 | } | ||
1406 | |||
1407 | ctx->frame_num = 0; | ||
1408 | |||
1409 | ctx->aborting = false; | ||
1410 | } | ||
1411 | |||
1412 | /* VB2 queue ops */ | ||
1413 | static struct vb2_ops delta_vb2_au_ops = { | ||
1414 | .queue_setup = delta_vb2_au_queue_setup, | ||
1415 | .buf_prepare = delta_vb2_au_prepare, | ||
1416 | .buf_queue = delta_vb2_au_queue, | ||
1417 | .wait_prepare = vb2_ops_wait_prepare, | ||
1418 | .wait_finish = vb2_ops_wait_finish, | ||
1419 | .start_streaming = delta_vb2_au_start_streaming, | ||
1420 | .stop_streaming = delta_vb2_au_stop_streaming, | ||
1421 | }; | ||
1422 | |||
1423 | static struct vb2_ops delta_vb2_frame_ops = { | ||
1424 | .queue_setup = delta_vb2_frame_queue_setup, | ||
1425 | .buf_prepare = delta_vb2_frame_prepare, | ||
1426 | .buf_finish = delta_vb2_frame_finish, | ||
1427 | .buf_queue = delta_vb2_frame_queue, | ||
1428 | .wait_prepare = vb2_ops_wait_prepare, | ||
1429 | .wait_finish = vb2_ops_wait_finish, | ||
1430 | .stop_streaming = delta_vb2_frame_stop_streaming, | ||
1431 | }; | ||
1432 | |||
1433 | /* | ||
1434 | * V4L2 file operations | ||
1435 | */ | ||
1436 | |||
1437 | static int queue_init(void *priv, | ||
1438 | struct vb2_queue *src_vq, struct vb2_queue *dst_vq) | ||
1439 | { | ||
1440 | struct vb2_queue *q; | ||
1441 | struct delta_ctx *ctx = priv; | ||
1442 | struct delta_dev *delta = ctx->dev; | ||
1443 | int ret; | ||
1444 | |||
1445 | /* setup vb2 queue for stream input */ | ||
1446 | q = src_vq; | ||
1447 | q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
1448 | q->io_modes = VB2_MMAP | VB2_DMABUF; | ||
1449 | q->drv_priv = ctx; | ||
1450 | /* overload vb2 buf with private au struct */ | ||
1451 | q->buf_struct_size = sizeof(struct delta_au); | ||
1452 | q->ops = &delta_vb2_au_ops; | ||
1453 | q->mem_ops = &vb2_dma_contig_memops; | ||
1454 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; | ||
1455 | q->lock = &delta->lock; | ||
1456 | q->dev = delta->dev; | ||
1457 | |||
1458 | ret = vb2_queue_init(q); | ||
1459 | if (ret) | ||
1460 | return ret; | ||
1461 | |||
1462 | /* setup vb2 queue for frame output */ | ||
1463 | q = dst_vq; | ||
1464 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1465 | q->io_modes = VB2_MMAP | VB2_DMABUF; | ||
1466 | q->drv_priv = ctx; | ||
1467 | /* overload vb2 buf with private frame struct */ | ||
1468 | q->buf_struct_size = sizeof(struct delta_frame) | ||
1469 | + DELTA_MAX_FRAME_PRIV_SIZE; | ||
1470 | q->ops = &delta_vb2_frame_ops; | ||
1471 | q->mem_ops = &vb2_dma_contig_memops; | ||
1472 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; | ||
1473 | q->lock = &delta->lock; | ||
1474 | q->dev = delta->dev; | ||
1475 | |||
1476 | return vb2_queue_init(q); | ||
1477 | } | ||
1478 | |||
1479 | static int delta_open(struct file *file) | ||
1480 | { | ||
1481 | struct delta_dev *delta = video_drvdata(file); | ||
1482 | struct delta_ctx *ctx = NULL; | ||
1483 | int ret = 0; | ||
1484 | |||
1485 | mutex_lock(&delta->lock); | ||
1486 | |||
1487 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
1488 | if (!ctx) { | ||
1489 | ret = -ENOMEM; | ||
1490 | goto err; | ||
1491 | } | ||
1492 | ctx->dev = delta; | ||
1493 | |||
1494 | v4l2_fh_init(&ctx->fh, video_devdata(file)); | ||
1495 | file->private_data = &ctx->fh; | ||
1496 | v4l2_fh_add(&ctx->fh); | ||
1497 | |||
1498 | INIT_WORK(&ctx->run_work, delta_run_work); | ||
1499 | mutex_init(&ctx->lock); | ||
1500 | |||
1501 | ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(delta->m2m_dev, ctx, | ||
1502 | queue_init); | ||
1503 | if (IS_ERR(ctx->fh.m2m_ctx)) { | ||
1504 | ret = PTR_ERR(ctx->fh.m2m_ctx); | ||
1505 | dev_err(delta->dev, "%s failed to initialize m2m context (%d)\n", | ||
1506 | DELTA_PREFIX, ret); | ||
1507 | goto err_fh_del; | ||
1508 | } | ||
1509 | |||
1510 | /* | ||
1511 | * wait stream format to determine which | ||
1512 | * decoder to open | ||
1513 | */ | ||
1514 | ctx->state = DELTA_STATE_WF_FORMAT; | ||
1515 | |||
1516 | INIT_LIST_HEAD(&ctx->dts); | ||
1517 | |||
1518 | /* set the instance name */ | ||
1519 | delta->instance_id++; | ||
1520 | snprintf(ctx->name, sizeof(ctx->name), "[%3d:----]", | ||
1521 | delta->instance_id); | ||
1522 | |||
1523 | /* default parameters for frame and stream */ | ||
1524 | set_default_params(ctx); | ||
1525 | |||
1526 | /* enable ST231 clocks */ | ||
1527 | if (delta->clk_st231) | ||
1528 | if (clk_prepare_enable(delta->clk_st231)) | ||
1529 | dev_warn(delta->dev, "failed to enable st231 clk\n"); | ||
1530 | |||
1531 | /* enable FLASH_PROMIP clock */ | ||
1532 | if (delta->clk_flash_promip) | ||
1533 | if (clk_prepare_enable(delta->clk_flash_promip)) | ||
1534 | dev_warn(delta->dev, "failed to enable delta promip clk\n"); | ||
1535 | |||
1536 | mutex_unlock(&delta->lock); | ||
1537 | |||
1538 | dev_dbg(delta->dev, "%s decoder instance created\n", ctx->name); | ||
1539 | |||
1540 | return 0; | ||
1541 | |||
1542 | err_fh_del: | ||
1543 | v4l2_fh_del(&ctx->fh); | ||
1544 | v4l2_fh_exit(&ctx->fh); | ||
1545 | kfree(ctx); | ||
1546 | err: | ||
1547 | mutex_unlock(&delta->lock); | ||
1548 | |||
1549 | return ret; | ||
1550 | } | ||
1551 | |||
1552 | static int delta_release(struct file *file) | ||
1553 | { | ||
1554 | struct delta_ctx *ctx = to_ctx(file->private_data); | ||
1555 | struct delta_dev *delta = ctx->dev; | ||
1556 | const struct delta_dec *dec = ctx->dec; | ||
1557 | |||
1558 | mutex_lock(&delta->lock); | ||
1559 | |||
1560 | /* close decoder */ | ||
1561 | call_dec_op(dec, close, ctx); | ||
1562 | |||
1563 | v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); | ||
1564 | |||
1565 | v4l2_fh_del(&ctx->fh); | ||
1566 | v4l2_fh_exit(&ctx->fh); | ||
1567 | |||
1568 | /* disable ST231 clocks */ | ||
1569 | if (delta->clk_st231) | ||
1570 | clk_disable_unprepare(delta->clk_st231); | ||
1571 | |||
1572 | /* disable FLASH_PROMIP clock */ | ||
1573 | if (delta->clk_flash_promip) | ||
1574 | clk_disable_unprepare(delta->clk_flash_promip); | ||
1575 | |||
1576 | dev_dbg(delta->dev, "%s decoder instance released\n", ctx->name); | ||
1577 | |||
1578 | kfree(ctx); | ||
1579 | |||
1580 | mutex_unlock(&delta->lock); | ||
1581 | return 0; | ||
1582 | } | ||
1583 | |||
1584 | /* V4L2 file ops */ | ||
1585 | static const struct v4l2_file_operations delta_fops = { | ||
1586 | .owner = THIS_MODULE, | ||
1587 | .open = delta_open, | ||
1588 | .release = delta_release, | ||
1589 | .unlocked_ioctl = video_ioctl2, | ||
1590 | .mmap = v4l2_m2m_fop_mmap, | ||
1591 | .poll = v4l2_m2m_fop_poll, | ||
1592 | }; | ||
1593 | |||
1594 | /* | ||
1595 | * Platform device operations | ||
1596 | */ | ||
1597 | |||
1598 | static int delta_register_device(struct delta_dev *delta) | ||
1599 | { | ||
1600 | int ret; | ||
1601 | struct video_device *vdev; | ||
1602 | |||
1603 | if (!delta) | ||
1604 | return -ENODEV; | ||
1605 | |||
1606 | delta->m2m_dev = v4l2_m2m_init(&delta_m2m_ops); | ||
1607 | if (IS_ERR(delta->m2m_dev)) { | ||
1608 | dev_err(delta->dev, "%s failed to initialize v4l2-m2m device\n", | ||
1609 | DELTA_PREFIX); | ||
1610 | ret = PTR_ERR(delta->m2m_dev); | ||
1611 | goto err; | ||
1612 | } | ||
1613 | |||
1614 | vdev = video_device_alloc(); | ||
1615 | if (!vdev) { | ||
1616 | dev_err(delta->dev, "%s failed to allocate video device\n", | ||
1617 | DELTA_PREFIX); | ||
1618 | ret = -ENOMEM; | ||
1619 | goto err_m2m_release; | ||
1620 | } | ||
1621 | |||
1622 | vdev->fops = &delta_fops; | ||
1623 | vdev->ioctl_ops = &delta_ioctl_ops; | ||
1624 | vdev->release = video_device_release; | ||
1625 | vdev->lock = &delta->lock; | ||
1626 | vdev->vfl_dir = VFL_DIR_M2M; | ||
1627 | vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; | ||
1628 | vdev->v4l2_dev = &delta->v4l2_dev; | ||
1629 | snprintf(vdev->name, sizeof(vdev->name), "%s-%s", | ||
1630 | DELTA_NAME, DELTA_FW_VERSION); | ||
1631 | |||
1632 | ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); | ||
1633 | if (ret) { | ||
1634 | dev_err(delta->dev, "%s failed to register video device\n", | ||
1635 | DELTA_PREFIX); | ||
1636 | goto err_vdev_release; | ||
1637 | } | ||
1638 | |||
1639 | delta->vdev = vdev; | ||
1640 | video_set_drvdata(vdev, delta); | ||
1641 | return 0; | ||
1642 | |||
1643 | err_vdev_release: | ||
1644 | video_device_release(vdev); | ||
1645 | err_m2m_release: | ||
1646 | v4l2_m2m_release(delta->m2m_dev); | ||
1647 | err: | ||
1648 | return ret; | ||
1649 | } | ||
1650 | |||
1651 | static void delta_unregister_device(struct delta_dev *delta) | ||
1652 | { | ||
1653 | if (!delta) | ||
1654 | return; | ||
1655 | |||
1656 | if (delta->m2m_dev) | ||
1657 | v4l2_m2m_release(delta->m2m_dev); | ||
1658 | |||
1659 | video_unregister_device(delta->vdev); | ||
1660 | } | ||
1661 | |||
1662 | static int delta_probe(struct platform_device *pdev) | ||
1663 | { | ||
1664 | struct delta_dev *delta; | ||
1665 | struct device *dev = &pdev->dev; | ||
1666 | int ret; | ||
1667 | |||
1668 | delta = devm_kzalloc(dev, sizeof(*delta), GFP_KERNEL); | ||
1669 | if (!delta) { | ||
1670 | ret = -ENOMEM; | ||
1671 | goto err; | ||
1672 | } | ||
1673 | |||
1674 | delta->dev = dev; | ||
1675 | delta->pdev = pdev; | ||
1676 | platform_set_drvdata(pdev, delta); | ||
1677 | |||
1678 | mutex_init(&delta->lock); | ||
1679 | |||
1680 | /* get clock resources */ | ||
1681 | delta->clk_delta = devm_clk_get(dev, "delta"); | ||
1682 | if (IS_ERR(delta->clk_delta)) { | ||
1683 | dev_dbg(dev, "%s can't get delta clock\n", DELTA_PREFIX); | ||
1684 | delta->clk_delta = NULL; | ||
1685 | } | ||
1686 | |||
1687 | delta->clk_st231 = devm_clk_get(dev, "delta-st231"); | ||
1688 | if (IS_ERR(delta->clk_st231)) { | ||
1689 | dev_dbg(dev, "%s can't get delta-st231 clock\n", DELTA_PREFIX); | ||
1690 | delta->clk_st231 = NULL; | ||
1691 | } | ||
1692 | |||
1693 | delta->clk_flash_promip = devm_clk_get(dev, "delta-flash-promip"); | ||
1694 | if (IS_ERR(delta->clk_flash_promip)) { | ||
1695 | dev_dbg(dev, "%s can't get delta-flash-promip clock\n", | ||
1696 | DELTA_PREFIX); | ||
1697 | delta->clk_flash_promip = NULL; | ||
1698 | } | ||
1699 | |||
1700 | /* init pm_runtime used for power management */ | ||
1701 | pm_runtime_set_autosuspend_delay(dev, DELTA_HW_AUTOSUSPEND_DELAY_MS); | ||
1702 | pm_runtime_use_autosuspend(dev); | ||
1703 | pm_runtime_set_suspended(dev); | ||
1704 | pm_runtime_enable(dev); | ||
1705 | |||
1706 | /* register all available decoders */ | ||
1707 | register_decoders(delta); | ||
1708 | |||
1709 | /* register all supported formats */ | ||
1710 | register_formats(delta); | ||
1711 | |||
1712 | /* register on V4L2 */ | ||
1713 | ret = v4l2_device_register(dev, &delta->v4l2_dev); | ||
1714 | if (ret) { | ||
1715 | dev_err(delta->dev, "%s failed to register V4L2 device\n", | ||
1716 | DELTA_PREFIX); | ||
1717 | goto err; | ||
1718 | } | ||
1719 | |||
1720 | delta->work_queue = create_workqueue(DELTA_NAME); | ||
1721 | if (!delta->work_queue) { | ||
1722 | dev_err(delta->dev, "%s failed to allocate work queue\n", | ||
1723 | DELTA_PREFIX); | ||
1724 | ret = -ENOMEM; | ||
1725 | goto err_v4l2; | ||
1726 | } | ||
1727 | |||
1728 | /* register device */ | ||
1729 | ret = delta_register_device(delta); | ||
1730 | if (ret) | ||
1731 | goto err_work_queue; | ||
1732 | |||
1733 | dev_info(dev, "%s %s registered as /dev/video%d\n", | ||
1734 | DELTA_PREFIX, delta->vdev->name, delta->vdev->num); | ||
1735 | |||
1736 | return 0; | ||
1737 | |||
1738 | err_work_queue: | ||
1739 | destroy_workqueue(delta->work_queue); | ||
1740 | err_v4l2: | ||
1741 | v4l2_device_unregister(&delta->v4l2_dev); | ||
1742 | err: | ||
1743 | return ret; | ||
1744 | } | ||
1745 | |||
1746 | static int delta_remove(struct platform_device *pdev) | ||
1747 | { | ||
1748 | struct delta_dev *delta = platform_get_drvdata(pdev); | ||
1749 | |||
1750 | delta_unregister_device(delta); | ||
1751 | |||
1752 | destroy_workqueue(delta->work_queue); | ||
1753 | |||
1754 | pm_runtime_put_autosuspend(delta->dev); | ||
1755 | pm_runtime_disable(delta->dev); | ||
1756 | |||
1757 | v4l2_device_unregister(&delta->v4l2_dev); | ||
1758 | |||
1759 | return 0; | ||
1760 | } | ||
1761 | |||
1762 | static int delta_runtime_suspend(struct device *dev) | ||
1763 | { | ||
1764 | struct delta_dev *delta = dev_get_drvdata(dev); | ||
1765 | |||
1766 | if (delta->clk_delta) | ||
1767 | clk_disable_unprepare(delta->clk_delta); | ||
1768 | |||
1769 | return 0; | ||
1770 | } | ||
1771 | |||
1772 | static int delta_runtime_resume(struct device *dev) | ||
1773 | { | ||
1774 | struct delta_dev *delta = dev_get_drvdata(dev); | ||
1775 | |||
1776 | if (delta->clk_delta) | ||
1777 | if (clk_prepare_enable(delta->clk_delta)) | ||
1778 | dev_warn(dev, "failed to prepare/enable delta clk\n"); | ||
1779 | |||
1780 | return 0; | ||
1781 | } | ||
1782 | |||
1783 | /* PM ops */ | ||
1784 | static const struct dev_pm_ops delta_pm_ops = { | ||
1785 | .runtime_suspend = delta_runtime_suspend, | ||
1786 | .runtime_resume = delta_runtime_resume, | ||
1787 | }; | ||
1788 | |||
1789 | static const struct of_device_id delta_match_types[] = { | ||
1790 | { | ||
1791 | .compatible = "st,st-delta", | ||
1792 | }, | ||
1793 | { | ||
1794 | /* end node */ | ||
1795 | } | ||
1796 | }; | ||
1797 | |||
1798 | MODULE_DEVICE_TABLE(of, delta_match_types); | ||
1799 | |||
1800 | static struct platform_driver delta_driver = { | ||
1801 | .probe = delta_probe, | ||
1802 | .remove = delta_remove, | ||
1803 | .driver = { | ||
1804 | .name = DELTA_NAME, | ||
1805 | .of_match_table = delta_match_types, | ||
1806 | .pm = &delta_pm_ops}, | ||
1807 | }; | ||
1808 | |||
1809 | module_platform_driver(delta_driver); | ||
1810 | |||
1811 | MODULE_LICENSE("GPL"); | ||
1812 | MODULE_AUTHOR("Hugues Fruchet <hugues.fruchet@st.com>"); | ||
1813 | MODULE_DESCRIPTION("STMicroelectronics DELTA video decoder V4L2 driver"); | ||
diff --git a/drivers/media/platform/sti/delta/delta.h b/drivers/media/platform/sti/delta/delta.h new file mode 100644 index 000000000000..74a42404bc50 --- /dev/null +++ b/drivers/media/platform/sti/delta/delta.h | |||
@@ -0,0 +1,514 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2015 | ||
3 | * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics. | ||
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | ||
6 | |||
7 | #ifndef DELTA_H | ||
8 | #define DELTA_H | ||
9 | |||
10 | #include <media/v4l2-device.h> | ||
11 | #include <media/v4l2-mem2mem.h> | ||
12 | |||
13 | #include "delta-cfg.h" | ||
14 | |||
15 | /* | ||
16 | * enum delta_state - state of decoding instance | ||
17 | * | ||
18 | *@DELTA_STATE_WF_FORMAT: | ||
19 | * Wait for compressed format to be set by V4L2 client in order | ||
20 | * to know what is the relevant decoder to open. | ||
21 | * | ||
22 | *@DELTA_STATE_WF_STREAMINFO: | ||
23 | * Wait for stream information to be available (bitstream | ||
24 | * header parsing is done). | ||
25 | * | ||
26 | *@DELTA_STATE_READY: | ||
27 | * Decoding instance is ready to decode compressed access unit. | ||
28 | * | ||
29 | */ | ||
30 | enum delta_state { | ||
31 | DELTA_STATE_WF_FORMAT, | ||
32 | DELTA_STATE_WF_STREAMINFO, | ||
33 | DELTA_STATE_READY, | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * struct delta_streaminfo - information about stream to decode | ||
38 | * | ||
39 | * @flags: validity of fields (crop, pixelaspect, other) | ||
40 | * @width: width of video stream | ||
41 | * @height: height "" | ||
42 | * @streamformat: fourcc compressed format of video (MJPEG, MPEG2, ...) | ||
43 | * @dpb: number of frames needed to decode a single frame | ||
44 | * (h264 dpb, up to 16) | ||
45 | * @crop: cropping window inside decoded frame (1920x1080@0,0 | ||
46 | * inside 1920x1088 frame for ex.) | ||
47 | * @pixelaspect: pixel aspect ratio of video (4/3, 5/4) | ||
48 | * @field: interlaced or not | ||
49 | * @profile: profile string | ||
50 | * @level: level string | ||
51 | * @other: other string information from codec | ||
52 | * @colorspace: colorspace identifier | ||
53 | * @xfer_func: transfer function identifier | ||
54 | * @ycbcr_enc: Y'CbCr encoding identifier | ||
55 | * @quantization: quantization identifier | ||
56 | */ | ||
57 | struct delta_streaminfo { | ||
58 | u32 flags; | ||
59 | u32 streamformat; | ||
60 | u32 width; | ||
61 | u32 height; | ||
62 | u32 dpb; | ||
63 | struct v4l2_rect crop; | ||
64 | struct v4l2_fract pixelaspect; | ||
65 | enum v4l2_field field; | ||
66 | u8 profile[32]; | ||
67 | u8 level[32]; | ||
68 | u8 other[32]; | ||
69 | enum v4l2_colorspace colorspace; | ||
70 | enum v4l2_xfer_func xfer_func; | ||
71 | enum v4l2_ycbcr_encoding ycbcr_enc; | ||
72 | enum v4l2_quantization quantization; | ||
73 | }; | ||
74 | |||
75 | #define DELTA_STREAMINFO_FLAG_CROP 0x0001 | ||
76 | #define DELTA_STREAMINFO_FLAG_PIXELASPECT 0x0002 | ||
77 | #define DELTA_STREAMINFO_FLAG_OTHER 0x0004 | ||
78 | |||
79 | /* | ||
80 | * struct delta_au - access unit structure. | ||
81 | * | ||
82 | * @vbuf: video buffer information for V4L2 | ||
83 | * @list: V4L2 m2m list that the frame belongs to | ||
84 | * @prepared: if set vaddr/paddr are resolved | ||
85 | * @vaddr: virtual address (kernel can read/write) | ||
86 | * @paddr: physical address (for hardware) | ||
87 | * @flags: access unit type (V4L2_BUF_FLAG_KEYFRAME/PFRAME/BFRAME) | ||
88 | * @dts: decoding timestamp of this access unit | ||
89 | */ | ||
90 | struct delta_au { | ||
91 | struct vb2_v4l2_buffer vbuf; /* keep first */ | ||
92 | struct list_head list; /* keep second */ | ||
93 | |||
94 | bool prepared; | ||
95 | u32 size; | ||
96 | void *vaddr; | ||
97 | dma_addr_t paddr; | ||
98 | u32 flags; | ||
99 | u64 dts; | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * struct delta_frameinfo - information about decoded frame | ||
104 | * | ||
105 | * @flags: validity of fields (crop, pixelaspect) | ||
106 | * @pixelformat: fourcc code for uncompressed video format | ||
107 | * @width: width of frame | ||
108 | * @height: height of frame | ||
109 | * @aligned_width: width of frame (with encoder or decoder alignment | ||
110 | * constraint) | ||
111 | * @aligned_height: height of frame (with encoder or decoder alignment | ||
112 | * constraint) | ||
113 | * @size: maximum size in bytes required for data | ||
114 | * @crop: cropping window inside frame (1920x1080@0,0 | ||
115 | * inside 1920x1088 frame for ex.) | ||
116 | * @pixelaspect: pixel aspect ratio of video (4/3, 5/4) | ||
117 | * @field: interlaced mode | ||
118 | * @colorspace: colorspace identifier | ||
119 | * @xfer_func: transfer function identifier | ||
120 | * @ycbcr_enc: Y'CbCr encoding identifier | ||
121 | * @quantization: quantization identifier | ||
122 | */ | ||
123 | struct delta_frameinfo { | ||
124 | u32 flags; | ||
125 | u32 pixelformat; | ||
126 | u32 width; | ||
127 | u32 height; | ||
128 | u32 aligned_width; | ||
129 | u32 aligned_height; | ||
130 | u32 size; | ||
131 | struct v4l2_rect crop; | ||
132 | struct v4l2_fract pixelaspect; | ||
133 | enum v4l2_field field; | ||
134 | enum v4l2_colorspace colorspace; | ||
135 | enum v4l2_xfer_func xfer_func; | ||
136 | enum v4l2_ycbcr_encoding ycbcr_enc; | ||
137 | enum v4l2_quantization quantization; | ||
138 | }; | ||
139 | |||
140 | #define DELTA_FRAMEINFO_FLAG_CROP 0x0001 | ||
141 | #define DELTA_FRAMEINFO_FLAG_PIXELASPECT 0x0002 | ||
142 | |||
143 | /* | ||
144 | * struct delta_frame - frame structure. | ||
145 | * | ||
146 | * @vbuf: video buffer information for V4L2 | ||
147 | * @list: V4L2 m2m list that the frame belongs to | ||
148 | * @info: frame information (width, height, format, alignment...) | ||
149 | * @prepared: if set pix/vaddr/paddr are resolved | ||
150 | * @index: frame index, aligned on V4L2 wow | ||
151 | * @vaddr: virtual address (kernel can read/write) | ||
152 | * @paddr: physical address (for hardware) | ||
153 | * @state: frame state for frame lifecycle tracking | ||
154 | * (DELTA_FRAME_FREE/DEC/OUT/REC/...) | ||
155 | * @flags: frame type (V4L2_BUF_FLAG_KEYFRAME/PFRAME/BFRAME) | ||
156 | * @dts: decoding timestamp of this frame | ||
157 | * @field: field order for interlaced frame | ||
158 | */ | ||
159 | struct delta_frame { | ||
160 | struct vb2_v4l2_buffer vbuf; /* keep first */ | ||
161 | struct list_head list; /* keep second */ | ||
162 | |||
163 | struct delta_frameinfo info; | ||
164 | bool prepared; | ||
165 | u32 index; | ||
166 | void *vaddr; | ||
167 | dma_addr_t paddr; | ||
168 | u32 state; | ||
169 | u32 flags; | ||
170 | u64 dts; | ||
171 | enum v4l2_field field; | ||
172 | }; | ||
173 | |||
174 | /* frame state for frame lifecycle tracking */ | ||
175 | #define DELTA_FRAME_FREE 0x00 /* is free and can be used for decoding */ | ||
176 | #define DELTA_FRAME_REF 0x01 /* is a reference frame */ | ||
177 | #define DELTA_FRAME_BSY 0x02 /* is owned by decoder and busy */ | ||
178 | #define DELTA_FRAME_DEC 0x04 /* contains decoded content */ | ||
179 | #define DELTA_FRAME_OUT 0x08 /* has been given to user */ | ||
180 | #define DELTA_FRAME_RDY 0x10 /* is ready but still held by decoder */ | ||
181 | #define DELTA_FRAME_M2M 0x20 /* is owned by mem2mem framework */ | ||
182 | |||
183 | /* | ||
184 | * struct delta_dts - decoding timestamp. | ||
185 | * | ||
186 | * @list: list to chain timestamps | ||
187 | * @val: timestamp in microseconds | ||
188 | */ | ||
189 | struct delta_dts { | ||
190 | struct list_head list; | ||
191 | u64 val; | ||
192 | }; | ||
193 | |||
194 | struct delta_ctx; | ||
195 | |||
196 | /* | ||
197 | * struct delta_dec - decoder structure. | ||
198 | * | ||
199 | * @name: name of this decoder | ||
200 | * @streamformat: input stream format that this decoder support | ||
201 | * @pixelformat: pixel format of decoded frame that this decoder support | ||
202 | * @max_width: (optional) maximum width that can decode this decoder | ||
203 | * if not set, maximum width is DELTA_MAX_WIDTH | ||
204 | * @max_height: (optional) maximum height that can decode this decoder | ||
205 | * if not set, maximum height is DELTA_MAX_HEIGHT | ||
206 | * @pm: (optional) if set, decoder will manage power on its own | ||
207 | * @open: open this decoder | ||
208 | * @close: close this decoder | ||
209 | * @setup_frame: setup frame to be used by decoder, see below | ||
210 | * @get_streaminfo: get stream related infos, see below | ||
211 | * @get_frameinfo: get decoded frame related infos, see below | ||
212 | * @set_frameinfo: (optional) set decoded frame related infos, see below | ||
213 | * @setup_frame: setup frame to be used by decoder, see below | ||
214 | * @decode: decode a single access unit, see below | ||
215 | * @get_frame: get the next decoded frame available, see below | ||
216 | * @recycle: recycle the given frame, see below | ||
217 | * @flush: (optional) flush decoder, see below | ||
218 | */ | ||
219 | struct delta_dec { | ||
220 | const char *name; | ||
221 | u32 streamformat; | ||
222 | u32 pixelformat; | ||
223 | u32 max_width; | ||
224 | u32 max_height; | ||
225 | bool pm; | ||
226 | |||
227 | /* | ||
228 | * decoder ops | ||
229 | */ | ||
230 | int (*open)(struct delta_ctx *ctx); | ||
231 | int (*close)(struct delta_ctx *ctx); | ||
232 | |||
233 | /* | ||
234 | * setup_frame() - setup frame to be used by decoder | ||
235 | * @ctx: (in) instance | ||
236 | * @frame: (in) frame to use | ||
237 | * @frame.index (in) identifier of frame | ||
238 | * @frame.vaddr (in) virtual address (kernel can read/write) | ||
239 | * @frame.paddr (in) physical address (for hardware) | ||
240 | * | ||
241 | * Frame is to be allocated by caller, then given | ||
242 | * to decoder through this call. | ||
243 | * Several frames must be given to decoder (dpb), | ||
244 | * each frame is identified using its index. | ||
245 | */ | ||
246 | int (*setup_frame)(struct delta_ctx *ctx, struct delta_frame *frame); | ||
247 | |||
248 | /* | ||
249 | * get_streaminfo() - get stream related infos | ||
250 | * @ctx: (in) instance | ||
251 | * @streaminfo: (out) width, height, dpb,... | ||
252 | * | ||
253 | * Precondition: stream header must have been successfully | ||
254 | * parsed to have this call successful & @streaminfo valid. | ||
255 | * Header parsing must be done using decode(), giving | ||
256 | * explicitly header access unit or first access unit of bitstream. | ||
257 | * If no valid header is found, get_streaminfo will return -ENODATA, | ||
258 | * in this case the next bistream access unit must be decoded till | ||
259 | * get_streaminfo becomes successful. | ||
260 | */ | ||
261 | int (*get_streaminfo)(struct delta_ctx *ctx, | ||
262 | struct delta_streaminfo *streaminfo); | ||
263 | |||
264 | /* | ||
265 | * get_frameinfo() - get decoded frame related infos | ||
266 | * @ctx: (in) instance | ||
267 | * @frameinfo: (out) width, height, alignment, crop, ... | ||
268 | * | ||
269 | * Precondition: get_streaminfo() must be successful | ||
270 | */ | ||
271 | int (*get_frameinfo)(struct delta_ctx *ctx, | ||
272 | struct delta_frameinfo *frameinfo); | ||
273 | |||
274 | /* | ||
275 | * set_frameinfo() - set decoded frame related infos | ||
276 | * @ctx: (in) instance | ||
277 | * @frameinfo: (out) width, height, alignment, crop, ... | ||
278 | * | ||
279 | * Optional. | ||
280 | * Typically used to negotiate with decoder the output | ||
281 | * frame if decoder can do post-processing. | ||
282 | */ | ||
283 | int (*set_frameinfo)(struct delta_ctx *ctx, | ||
284 | struct delta_frameinfo *frameinfo); | ||
285 | |||
286 | /* | ||
287 | * decode() - decode a single access unit | ||
288 | * @ctx: (in) instance | ||
289 | * @au: (in/out) access unit | ||
290 | * @au.size (in) size of au to decode | ||
291 | * @au.vaddr (in) virtual address (kernel can read/write) | ||
292 | * @au.paddr (in) physical address (for hardware) | ||
293 | * @au.flags (out) au type (V4L2_BUF_FLAG_KEYFRAME/ | ||
294 | * PFRAME/BFRAME) | ||
295 | * | ||
296 | * Decode the access unit given. Decode is synchronous; | ||
297 | * access unit memory is no more needed after this call. | ||
298 | * After this call, none, one or several frames could | ||
299 | * have been decoded, which can be retrieved using | ||
300 | * get_frame(). | ||
301 | */ | ||
302 | int (*decode)(struct delta_ctx *ctx, struct delta_au *au); | ||
303 | |||
304 | /* | ||
305 | * get_frame() - get the next decoded frame available | ||
306 | * @ctx: (in) instance | ||
307 | * @frame: (out) frame with decoded data: | ||
308 | * @frame.index (out) identifier of frame | ||
309 | * @frame.field (out) field order for interlaced frame | ||
310 | * @frame.state (out) frame state for frame lifecycle tracking | ||
311 | * @frame.flags (out) frame type (V4L2_BUF_FLAG_KEYFRAME/ | ||
312 | * PFRAME/BFRAME) | ||
313 | * | ||
314 | * Get the next available decoded frame. | ||
315 | * If no frame is available, -ENODATA is returned. | ||
316 | * If a frame is available, frame structure is filled with | ||
317 | * relevant data, frame.index identifying this exact frame. | ||
318 | * When this frame is no more needed by upper layers, | ||
319 | * recycle() must be called giving this frame identifier. | ||
320 | */ | ||
321 | int (*get_frame)(struct delta_ctx *ctx, struct delta_frame **frame); | ||
322 | |||
323 | /* | ||
324 | * recycle() - recycle the given frame | ||
325 | * @ctx: (in) instance | ||
326 | * @frame: (in) frame to recycle: | ||
327 | * @frame.index (in) identifier of frame | ||
328 | * | ||
329 | * recycle() is to be called by user when the decoded frame | ||
330 | * is no more needed (composition/display done). | ||
331 | * This frame will then be reused by decoder to proceed | ||
332 | * with next frame decoding. | ||
333 | * If not enough frames have been provided through setup_frame(), | ||
334 | * or recycle() is not called fast enough, the decoder can run out | ||
335 | * of available frames to proceed with decoding (starvation). | ||
336 | * This case is guarded by wq_recycle wait queue which ensures that | ||
337 | * decoder is called only if at least one frame is available. | ||
338 | */ | ||
339 | int (*recycle)(struct delta_ctx *ctx, struct delta_frame *frame); | ||
340 | |||
341 | /* | ||
342 | * flush() - flush decoder | ||
343 | * @ctx: (in) instance | ||
344 | * | ||
345 | * Optional. | ||
346 | * Reset decoder context and discard all internal buffers. | ||
347 | * This allows implementation of seek, which leads to discontinuity | ||
348 | * of input bitstream that decoder must know to restart its internal | ||
349 | * decoding logic. | ||
350 | */ | ||
351 | int (*flush)(struct delta_ctx *ctx); | ||
352 | }; | ||
353 | |||
354 | struct delta_dev; | ||
355 | |||
356 | /* | ||
357 | * struct delta_ctx - instance structure. | ||
358 | * | ||
359 | * @flags: validity of fields (streaminfo) | ||
360 | * @fh: V4L2 file handle | ||
361 | * @dev: device context | ||
362 | * @dec: selected decoder context for this instance | ||
363 | * @state: instance state | ||
364 | * @frame_num: frame number | ||
365 | * @au_num: access unit number | ||
366 | * @max_au_size: max size of an access unit | ||
367 | * @streaminfo: stream information (width, height, dpb, interlacing...) | ||
368 | * @frameinfo: frame information (width, height, format, alignment...) | ||
369 | * @nb_of_frames: number of frames available for decoding | ||
370 | * @frames: array of decoding frames to keep track of frame | ||
371 | * state and manage frame recycling | ||
372 | * @decoded_frames: nb of decoded frames from opening | ||
373 | * @output_frames: nb of output frames from opening | ||
374 | * @dropped_frames: nb of frames dropped (ie access unit not parsed | ||
375 | * or frame decoded but not output) | ||
376 | * @stream_errors: nb of stream errors (corrupted, not supported, ...) | ||
377 | * @decode_errors: nb of decode errors (firmware error) | ||
378 | * @sys_errors: nb of system errors (memory, ipc, ...) | ||
379 | * @dts: FIFO of decoding timestamp. | ||
380 | * output frames are timestamped with incoming access | ||
381 | * unit timestamps using this fifo. | ||
382 | * @name: string naming this instance (debug purpose) | ||
383 | * @run_work: decoding work | ||
384 | * @lock: lock for decoding work serialization | ||
385 | * @aborting: true if current job aborted | ||
386 | * @priv: private decoder context for this instance, allocated | ||
387 | * by decoder @open time. | ||
388 | */ | ||
389 | struct delta_ctx { | ||
390 | u32 flags; | ||
391 | struct v4l2_fh fh; | ||
392 | struct delta_dev *dev; | ||
393 | const struct delta_dec *dec; | ||
394 | enum delta_state state; | ||
395 | u32 frame_num; | ||
396 | u32 au_num; | ||
397 | size_t max_au_size; | ||
398 | struct delta_streaminfo streaminfo; | ||
399 | struct delta_frameinfo frameinfo; | ||
400 | u32 nb_of_frames; | ||
401 | struct delta_frame *frames[DELTA_MAX_FRAMES]; | ||
402 | u32 decoded_frames; | ||
403 | u32 output_frames; | ||
404 | u32 dropped_frames; | ||
405 | u32 stream_errors; | ||
406 | u32 decode_errors; | ||
407 | u32 sys_errors; | ||
408 | struct list_head dts; | ||
409 | char name[100]; | ||
410 | struct work_struct run_work; | ||
411 | struct mutex lock; | ||
412 | bool aborting; | ||
413 | void *priv; | ||
414 | }; | ||
415 | |||
416 | #define DELTA_FLAG_STREAMINFO 0x0001 | ||
417 | #define DELTA_FLAG_FRAMEINFO 0x0002 | ||
418 | |||
419 | #define DELTA_MAX_FORMATS DELTA_MAX_DECODERS | ||
420 | |||
421 | /* | ||
422 | * struct delta_dev - device struct, 1 per probe (so single one for | ||
423 | * all platform life) | ||
424 | * | ||
425 | * @v4l2_dev: v4l2 device | ||
426 | * @vdev: v4l2 video device | ||
427 | * @pdev: platform device | ||
428 | * @dev: device | ||
429 | * @m2m_dev: memory-to-memory V4L2 device | ||
430 | * @lock: device lock, for crit section & V4L2 ops serialization. | ||
431 | * @clk_delta: delta main clock | ||
432 | * @clk_st231: st231 coprocessor main clock | ||
433 | * @clk_flash_promip: flash promip clock | ||
434 | * @decoders: list of registered decoders | ||
435 | * @nb_of_decoders: nb of registered decoders | ||
436 | * @pixelformats: supported uncompressed video formats | ||
437 | * @nb_of_pixelformats: number of supported umcompressed video formats | ||
438 | * @streamformats: supported compressed video formats | ||
439 | * @nb_of_streamformats:number of supported compressed video formats | ||
440 | * @instance_id: rolling counter identifying an instance (debug purpose) | ||
441 | * @work_queue: decoding job work queue | ||
442 | */ | ||
443 | struct delta_dev { | ||
444 | struct v4l2_device v4l2_dev; | ||
445 | struct video_device *vdev; | ||
446 | struct platform_device *pdev; | ||
447 | struct device *dev; | ||
448 | struct v4l2_m2m_dev *m2m_dev; | ||
449 | struct mutex lock; | ||
450 | struct clk *clk_delta; | ||
451 | struct clk *clk_st231; | ||
452 | struct clk *clk_flash_promip; | ||
453 | const struct delta_dec *decoders[DELTA_MAX_DECODERS]; | ||
454 | u32 nb_of_decoders; | ||
455 | u32 pixelformats[DELTA_MAX_FORMATS]; | ||
456 | u32 nb_of_pixelformats; | ||
457 | u32 streamformats[DELTA_MAX_FORMATS]; | ||
458 | u32 nb_of_streamformats; | ||
459 | u8 instance_id; | ||
460 | struct workqueue_struct *work_queue; | ||
461 | }; | ||
462 | |||
463 | static inline char *frame_type_str(u32 flags) | ||
464 | { | ||
465 | if (flags & V4L2_BUF_FLAG_KEYFRAME) | ||
466 | return "I"; | ||
467 | if (flags & V4L2_BUF_FLAG_PFRAME) | ||
468 | return "P"; | ||
469 | if (flags & V4L2_BUF_FLAG_BFRAME) | ||
470 | return "B"; | ||
471 | return "?"; | ||
472 | } | ||
473 | |||
474 | static inline char *frame_field_str(enum v4l2_field field) | ||
475 | { | ||
476 | if (field == V4L2_FIELD_NONE) | ||
477 | return "-"; | ||
478 | if (field == V4L2_FIELD_TOP) | ||
479 | return "T"; | ||
480 | if (field == V4L2_FIELD_BOTTOM) | ||
481 | return "B"; | ||
482 | if (field == V4L2_FIELD_INTERLACED) | ||
483 | return "I"; | ||
484 | if (field == V4L2_FIELD_INTERLACED_TB) | ||
485 | return "TB"; | ||
486 | if (field == V4L2_FIELD_INTERLACED_BT) | ||
487 | return "BT"; | ||
488 | return "?"; | ||
489 | } | ||
490 | |||
491 | static inline char *frame_state_str(u32 state, char *str, unsigned int len) | ||
492 | { | ||
493 | snprintf(str, len, "%s %s %s %s %s %s", | ||
494 | (state & DELTA_FRAME_REF) ? "ref" : " ", | ||
495 | (state & DELTA_FRAME_BSY) ? "bsy" : " ", | ||
496 | (state & DELTA_FRAME_DEC) ? "dec" : " ", | ||
497 | (state & DELTA_FRAME_OUT) ? "out" : " ", | ||
498 | (state & DELTA_FRAME_M2M) ? "m2m" : " ", | ||
499 | (state & DELTA_FRAME_RDY) ? "rdy" : " "); | ||
500 | return str; | ||
501 | } | ||
502 | |||
503 | int delta_get_frameinfo_default(struct delta_ctx *ctx, | ||
504 | struct delta_frameinfo *frameinfo); | ||
505 | int delta_recycle_default(struct delta_ctx *pctx, | ||
506 | struct delta_frame *frame); | ||
507 | |||
508 | int delta_get_free_frame(struct delta_ctx *ctx, | ||
509 | struct delta_frame **pframe); | ||
510 | |||
511 | int delta_get_sync(struct delta_ctx *ctx); | ||
512 | void delta_put_autosuspend(struct delta_ctx *ctx); | ||
513 | |||
514 | #endif /* DELTA_H */ | ||