Skip to content

Commit c5377fb

Browse files
Elyotnachewitt
authored andcommitted
WIP: media: meson: vdec: add support for MPEG4 decoding
Add support for V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_XVID and V4L2_PIX_FMT_H.263. This is experimental !!! Signed-off-by: Maxime Jourdan <[email protected]>
1 parent 7243c89 commit c5377fb

File tree

4 files changed

+305
-1
lines changed

4 files changed

+305
-1
lines changed

drivers/staging/media/meson/vdec/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33

44
meson-vdec-objs = esparser.o vdec.o vdec_helpers.o vdec_platform.o
55
meson-vdec-objs += vdec_1.o vdec_hevc.o
6-
meson-vdec-objs += codec_mpeg12.o codec_h264.o codec_hevc_common.o codec_hevc.o codec_vp9.o
6+
meson-vdec-objs += codec_mpeg12.o codec_mpeg4.o codec_h264.o codec_hevc_common.o codec_hevc.o codec_vp9.o
77

88
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson-vdec.o
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (C) 2018 Maxime Jourdan <[email protected]>
4+
*/
5+
6+
#include <media/v4l2-mem2mem.h>
7+
#include <media/videobuf2-dma-contig.h>
8+
9+
#include "vdec_helpers.h"
10+
#include "dos_regs.h"
11+
12+
#define SIZE_WORKSPACE SZ_1M
13+
/* Offset added by firmware, to substract from workspace paddr */
14+
#define DCAC_BUFF_START_IP 0x02b00000
15+
16+
/* map firmware registers to known MPEG4 functions */
17+
#define MREG_BUFFERIN AV_SCRATCH_8
18+
#define MREG_BUFFEROUT AV_SCRATCH_9
19+
#define MP4_NOT_CODED_CNT AV_SCRATCH_A
20+
#define MP4_OFFSET_REG AV_SCRATCH_C
21+
#define MEM_OFFSET_REG AV_SCRATCH_F
22+
#define MREG_FATAL_ERROR AV_SCRATCH_L
23+
24+
#define BUF_IDX_MASK GENMASK(2, 0)
25+
#define INTERLACE_FLAG BIT(7)
26+
#define TOP_FIELD_FIRST_FLAG BIT(6)
27+
28+
struct codec_mpeg4 {
29+
/* Buffer for the MPEG4 Workspace */
30+
void *workspace_vaddr;
31+
dma_addr_t workspace_paddr;
32+
};
33+
34+
static int codec_mpeg4_can_recycle(struct amvdec_core *core)
35+
{
36+
return !amvdec_read_dos(core, MREG_BUFFERIN);
37+
}
38+
39+
static void codec_mpeg4_recycle(struct amvdec_core *core, u32 buf_idx)
40+
{
41+
amvdec_write_dos(core, MREG_BUFFERIN, ~BIT(buf_idx));
42+
}
43+
44+
static int codec_mpeg4_start(struct amvdec_session *sess) {
45+
struct amvdec_core *core = sess->core;
46+
struct codec_mpeg4 *mpeg4 = sess->priv;
47+
int ret;
48+
49+
mpeg4 = kzalloc(sizeof(*mpeg4), GFP_KERNEL);
50+
if (!mpeg4)
51+
return -ENOMEM;
52+
53+
/* Allocate some memory for the MPEG4 decoder's state */
54+
mpeg4->workspace_vaddr = dma_alloc_coherent(core->dev, SIZE_WORKSPACE,
55+
&mpeg4->workspace_paddr,
56+
GFP_KERNEL);
57+
if (!mpeg4->workspace_vaddr) {
58+
dev_err(core->dev, "Failed to request MPEG4 Workspace\n");
59+
ret = -ENOMEM;
60+
goto free_mpeg4;
61+
}
62+
63+
/* Canvas regs: AV_SCRATCH_0-AV_SCRATCH_4;AV_SCRATCH_G-AV_SCRATCH_J */
64+
amvdec_set_canvases(sess, (u32[]){ AV_SCRATCH_0, AV_SCRATCH_G, 0 },
65+
(u32[]){ 4, 4, 0 });
66+
67+
amvdec_write_dos(core, MEM_OFFSET_REG,
68+
mpeg4->workspace_paddr - DCAC_BUFF_START_IP);
69+
amvdec_write_dos(core, PSCALE_CTRL, 0);
70+
amvdec_write_dos(core, MP4_NOT_CODED_CNT, 0);
71+
amvdec_write_dos(core, MREG_BUFFERIN, 0);
72+
amvdec_write_dos(core, MREG_BUFFEROUT, 0);
73+
amvdec_write_dos(core, MREG_FATAL_ERROR, 0);
74+
amvdec_write_dos(core, MDEC_PIC_DC_THRESH, 0x404038aa);
75+
76+
sess->keyframe_found = 1;
77+
sess->priv = mpeg4;
78+
79+
return 0;
80+
81+
free_mpeg4:
82+
kfree(mpeg4);
83+
return ret;
84+
}
85+
86+
static int codec_mpeg4_stop(struct amvdec_session *sess)
87+
{
88+
struct codec_mpeg4 *mpeg4 = sess->priv;
89+
struct amvdec_core *core = sess->core;
90+
91+
if (mpeg4->workspace_vaddr) {
92+
dma_free_coherent(core->dev, SIZE_WORKSPACE,
93+
mpeg4->workspace_vaddr,
94+
mpeg4->workspace_paddr);
95+
mpeg4->workspace_vaddr = 0;
96+
}
97+
98+
return 0;
99+
}
100+
101+
static irqreturn_t codec_mpeg4_isr(struct amvdec_session *sess)
102+
{
103+
struct amvdec_core *core = sess->core;
104+
u32 reg;
105+
u32 buffer_index;
106+
u32 field = V4L2_FIELD_NONE;
107+
108+
reg = amvdec_read_dos(core, MREG_FATAL_ERROR);
109+
if (reg == 1) {
110+
dev_err(core->dev, "mpeg4 fatal error\n");
111+
amvdec_abort(sess);
112+
return IRQ_HANDLED;
113+
}
114+
115+
reg = amvdec_read_dos(core, MREG_BUFFEROUT);
116+
if (!reg)
117+
goto end;
118+
119+
buffer_index = reg & BUF_IDX_MASK;
120+
if (reg & INTERLACE_FLAG)
121+
field = (reg & TOP_FIELD_FIRST_FLAG) ?
122+
V4L2_FIELD_INTERLACED_TB :
123+
V4L2_FIELD_INTERLACED_BT;
124+
125+
amvdec_dst_buf_done_idx(sess, buffer_index, -1, field);
126+
amvdec_write_dos(core, MREG_BUFFEROUT, 0);
127+
128+
end:
129+
amvdec_write_dos(core, ASSIST_MBOX1_CLR_REG, 1);
130+
return IRQ_HANDLED;
131+
}
132+
133+
struct amvdec_codec_ops codec_mpeg4_ops = {
134+
.start = codec_mpeg4_start,
135+
.stop = codec_mpeg4_stop,
136+
.isr = codec_mpeg4_isr,
137+
.can_recycle = codec_mpeg4_can_recycle,
138+
.recycle = codec_mpeg4_recycle,
139+
};
140+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
/*
3+
* Copyright (C) 2018 Maxime Jourdan <[email protected]>
4+
*/
5+
6+
#ifndef __MESON_VDEC_CODEC_MPEG4_H_
7+
#define __MESON_VDEC_CODEC_MPEG4_H_
8+
9+
#include "vdec.h"
10+
11+
extern struct amvdec_codec_ops codec_mpeg4_ops;
12+
13+
#endif

drivers/staging/media/meson/vdec/vdec_platform.c

+151
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,43 @@
1010
#include "vdec_1.h"
1111
#include "vdec_hevc.h"
1212
#include "codec_mpeg12.h"
13+
#include "codec_mpeg4.h"
1314
#include "codec_h264.h"
1415
#include "codec_hevc.h"
1516
#include "codec_vp9.h"
1617

1718
static const struct amvdec_format vdec_formats_gxbb[] = {
1819
{
20+
.pixfmt = V4L2_PIX_FMT_MPEG4,
21+
.min_buffers = 8,
22+
.max_buffers = 8,
23+
.max_width = 1920,
24+
.max_height = 1080,
25+
.vdec_ops = &vdec_1_ops,
26+
.codec_ops = &codec_mpeg4_ops,
27+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
28+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
29+
}, {
30+
.pixfmt = V4L2_PIX_FMT_H263,
31+
.min_buffers = 8,
32+
.max_buffers = 8,
33+
.max_width = 1920,
34+
.max_height = 1080,
35+
.vdec_ops = &vdec_1_ops,
36+
.codec_ops = &codec_mpeg4_ops,
37+
.firmware_path = "meson/vdec/gxl_h263.bin",
38+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
39+
}, {
40+
.pixfmt = V4L2_PIX_FMT_XVID,
41+
.min_buffers = 8,
42+
.max_buffers = 8,
43+
.max_width = 1920,
44+
.max_height = 1080,
45+
.vdec_ops = &vdec_1_ops,
46+
.codec_ops = &codec_mpeg4_ops,
47+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
48+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
49+
}, {
1950
.pixfmt = V4L2_PIX_FMT_H264,
2051
.min_buffers = 2,
2152
.max_buffers = 24,
@@ -54,6 +85,36 @@ static const struct amvdec_format vdec_formats_gxbb[] = {
5485

5586
static const struct amvdec_format vdec_formats_gxl[] = {
5687
{
88+
.pixfmt = V4L2_PIX_FMT_MPEG4,
89+
.min_buffers = 8,
90+
.max_buffers = 8,
91+
.max_width = 1920,
92+
.max_height = 1080,
93+
.vdec_ops = &vdec_1_ops,
94+
.codec_ops = &codec_mpeg4_ops,
95+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
96+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
97+
}, {
98+
.pixfmt = V4L2_PIX_FMT_H263,
99+
.min_buffers = 8,
100+
.max_buffers = 8,
101+
.max_width = 1920,
102+
.max_height = 1080,
103+
.vdec_ops = &vdec_1_ops,
104+
.codec_ops = &codec_mpeg4_ops,
105+
.firmware_path = "meson/vdec/gxl_h263.bin",
106+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
107+
}, {
108+
.pixfmt = V4L2_PIX_FMT_XVID,
109+
.min_buffers = 8,
110+
.max_buffers = 8,
111+
.max_width = 1920,
112+
.max_height = 1080,
113+
.vdec_ops = &vdec_1_ops,
114+
.codec_ops = &codec_mpeg4_ops,
115+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
116+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
117+
}, {
57118
.pixfmt = V4L2_PIX_FMT_VP9,
58119
.min_buffers = 16,
59120
.max_buffers = 24,
@@ -116,6 +177,36 @@ static const struct amvdec_format vdec_formats_gxl[] = {
116177

117178
static const struct amvdec_format vdec_formats_gxm[] = {
118179
{
180+
.pixfmt = V4L2_PIX_FMT_MPEG4,
181+
.min_buffers = 8,
182+
.max_buffers = 8,
183+
.max_width = 1920,
184+
.max_height = 1080,
185+
.vdec_ops = &vdec_1_ops,
186+
.codec_ops = &codec_mpeg4_ops,
187+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
188+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
189+
}, {
190+
.pixfmt = V4L2_PIX_FMT_H263,
191+
.min_buffers = 8,
192+
.max_buffers = 8,
193+
.max_width = 1920,
194+
.max_height = 1080,
195+
.vdec_ops = &vdec_1_ops,
196+
.codec_ops = &codec_mpeg4_ops,
197+
.firmware_path = "meson/vdec/gxl_h263.bin",
198+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
199+
}, {
200+
.pixfmt = V4L2_PIX_FMT_XVID,
201+
.min_buffers = 8,
202+
.max_buffers = 8,
203+
.max_width = 1920,
204+
.max_height = 1080,
205+
.vdec_ops = &vdec_1_ops,
206+
.codec_ops = &codec_mpeg4_ops,
207+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
208+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
209+
}, {
119210
.pixfmt = V4L2_PIX_FMT_H264,
120211
.min_buffers = 2,
121212
.max_buffers = 24,
@@ -166,6 +257,36 @@ static const struct amvdec_format vdec_formats_gxm[] = {
166257

167258
static const struct amvdec_format vdec_formats_g12a[] = {
168259
{
260+
.pixfmt = V4L2_PIX_FMT_MPEG4,
261+
.min_buffers = 8,
262+
.max_buffers = 8,
263+
.max_width = 1920,
264+
.max_height = 1080,
265+
.vdec_ops = &vdec_1_ops,
266+
.codec_ops = &codec_mpeg4_ops,
267+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
268+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
269+
}, {
270+
.pixfmt = V4L2_PIX_FMT_H263,
271+
.min_buffers = 8,
272+
.max_buffers = 8,
273+
.max_width = 1920,
274+
.max_height = 1080,
275+
.vdec_ops = &vdec_1_ops,
276+
.codec_ops = &codec_mpeg4_ops,
277+
.firmware_path = "meson/vdec/gxl_h263.bin",
278+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
279+
}, {
280+
.pixfmt = V4L2_PIX_FMT_XVID,
281+
.min_buffers = 8,
282+
.max_buffers = 8,
283+
.max_width = 1920,
284+
.max_height = 1080,
285+
.vdec_ops = &vdec_1_ops,
286+
.codec_ops = &codec_mpeg4_ops,
287+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
288+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
289+
}, {
169290
.pixfmt = V4L2_PIX_FMT_VP9,
170291
.min_buffers = 16,
171292
.max_buffers = 24,
@@ -228,6 +349,36 @@ static const struct amvdec_format vdec_formats_g12a[] = {
228349

229350
static const struct amvdec_format vdec_formats_sm1[] = {
230351
{
352+
.pixfmt = V4L2_PIX_FMT_MPEG4,
353+
.min_buffers = 8,
354+
.max_buffers = 8,
355+
.max_width = 1920,
356+
.max_height = 1080,
357+
.vdec_ops = &vdec_1_ops,
358+
.codec_ops = &codec_mpeg4_ops,
359+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
360+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
361+
}, {
362+
.pixfmt = V4L2_PIX_FMT_H263,
363+
.min_buffers = 8,
364+
.max_buffers = 8,
365+
.max_width = 1920,
366+
.max_height = 1080,
367+
.vdec_ops = &vdec_1_ops,
368+
.codec_ops = &codec_mpeg4_ops,
369+
.firmware_path = "meson/vdec/gxl_h263.bin",
370+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
371+
}, {
372+
.pixfmt = V4L2_PIX_FMT_XVID,
373+
.min_buffers = 8,
374+
.max_buffers = 8,
375+
.max_width = 1920,
376+
.max_height = 1080,
377+
.vdec_ops = &vdec_1_ops,
378+
.codec_ops = &codec_mpeg4_ops,
379+
.firmware_path = "meson/vdec/gxl_mpeg4_5.bin",
380+
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
381+
}, {
231382
.pixfmt = V4L2_PIX_FMT_VP9,
232383
.min_buffers = 16,
233384
.max_buffers = 24,

0 commit comments

Comments
 (0)