Skip to content

Commit 8e4aaa6

Browse files
pH5mchehab
authored andcommitted
media: hantro: add initial i.MX8MQ support
This enables h.264, MPEG-2, and VP8 decoding on the Hantro G1 on i.MX8MQ, with post-processing support. Signed-off-by: Philipp Zabel <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 4e6ea66 commit 8e4aaa6

File tree

5 files changed

+239
-4
lines changed

5 files changed

+239
-4
lines changed

drivers/staging/media/hantro/Kconfig

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
# SPDX-License-Identifier: GPL-2.0
22
config VIDEO_HANTRO
33
tristate "Hantro VPU driver"
4-
depends on ARCH_ROCKCHIP || COMPILE_TEST
4+
depends on ARCH_MXC || ARCH_ROCKCHIP || COMPILE_TEST
55
depends on VIDEO_DEV && VIDEO_V4L2 && MEDIA_CONTROLLER
66
depends on MEDIA_CONTROLLER_REQUEST_API
77
select VIDEOBUF2_DMA_CONTIG
88
select VIDEOBUF2_VMALLOC
99
select V4L2_MEM2MEM_DEV
1010
help
11-
Support for the Hantro IP based Video Processing Unit present on
12-
Rockchip SoC, which accelerates video and image encoding and
13-
decoding.
11+
Support for the Hantro IP based Video Processing Units present on
12+
Rockchip and NXP i.MX8M SoCs, which accelerate video and image
13+
encoding and decoding.
1414
To compile this driver as a module, choose M here: the module
1515
will be called hantro-vpu.
1616

17+
config VIDEO_HANTRO_IMX8M
18+
bool "Hantro VPU i.MX8M support"
19+
depends on VIDEO_HANTRO
20+
depends on ARCH_MXC || COMPILE_TEST
21+
default y
22+
help
23+
Enable support for i.MX8M SoCs.
24+
1725
config VIDEO_HANTRO_ROCKCHIP
1826
bool "Hantro VPU Rockchip support"
1927
depends on VIDEO_HANTRO

drivers/staging/media/hantro/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ hantro-vpu-y += \
1616
hantro_mpeg2.o \
1717
hantro_vp8.o
1818

19+
hantro-vpu-$(CONFIG_VIDEO_HANTRO_IMX8M) += \
20+
imx8m_vpu_hw.o
21+
1922
hantro-vpu-$(CONFIG_VIDEO_HANTRO_ROCKCHIP) += \
2023
rk3288_vpu_hw.o \
2124
rk3399_vpu_hw.o

drivers/staging/media/hantro/hantro_drv.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,9 @@ static const struct of_device_id of_hantro_match[] = {
498498
{ .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, },
499499
{ .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, },
500500
{ .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, },
501+
#endif
502+
#ifdef CONFIG_VIDEO_HANTRO_IMX8M
503+
{ .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, },
501504
#endif
502505
{ /* sentinel */ }
503506
};

drivers/staging/media/hantro/hantro_hw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ enum hantro_enc_fmt {
151151
extern const struct hantro_variant rk3399_vpu_variant;
152152
extern const struct hantro_variant rk3328_vpu_variant;
153153
extern const struct hantro_variant rk3288_vpu_variant;
154+
extern const struct hantro_variant imx8mq_vpu_variant;
154155

155156
extern const struct hantro_postproc_regs hantro_g1_postproc_regs;
156157

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Hantro VPU codec driver
4+
*
5+
* Copyright (C) 2019 Pengutronix, Philipp Zabel <[email protected]>
6+
*/
7+
8+
#include <linux/clk.h>
9+
#include <linux/delay.h>
10+
11+
#include "hantro.h"
12+
#include "hantro_jpeg.h"
13+
#include "hantro_g1_regs.h"
14+
15+
#define CTRL_SOFT_RESET 0x00
16+
#define RESET_G1 BIT(1)
17+
#define RESET_G2 BIT(0)
18+
19+
#define CTRL_CLOCK_ENABLE 0x04
20+
#define CLOCK_G1 BIT(1)
21+
#define CLOCK_G2 BIT(0)
22+
23+
#define CTRL_G1_DEC_FUSE 0x08
24+
#define CTRL_G1_PP_FUSE 0x0c
25+
#define CTRL_G2_DEC_FUSE 0x10
26+
27+
static void imx8m_soft_reset(struct hantro_dev *vpu, u32 reset_bits)
28+
{
29+
u32 val;
30+
31+
/* Assert */
32+
val = readl(vpu->ctrl_base + CTRL_SOFT_RESET);
33+
val &= ~reset_bits;
34+
writel(val, vpu->ctrl_base + CTRL_SOFT_RESET);
35+
36+
udelay(2);
37+
38+
/* Release */
39+
val = readl(vpu->ctrl_base + CTRL_SOFT_RESET);
40+
val |= reset_bits;
41+
writel(val, vpu->ctrl_base + CTRL_SOFT_RESET);
42+
}
43+
44+
static void imx8m_clk_enable(struct hantro_dev *vpu, u32 clock_bits)
45+
{
46+
u32 val;
47+
48+
val = readl(vpu->ctrl_base + CTRL_CLOCK_ENABLE);
49+
val |= clock_bits;
50+
writel(val, vpu->ctrl_base + CTRL_CLOCK_ENABLE);
51+
}
52+
53+
static int imx8mq_runtime_resume(struct hantro_dev *vpu)
54+
{
55+
int ret;
56+
57+
ret = clk_bulk_prepare_enable(vpu->variant->num_clocks, vpu->clocks);
58+
if (ret) {
59+
dev_err(vpu->dev, "Failed to enable clocks\n");
60+
return ret;
61+
}
62+
63+
imx8m_soft_reset(vpu, RESET_G1 | RESET_G2);
64+
imx8m_clk_enable(vpu, CLOCK_G1 | CLOCK_G2);
65+
66+
/* Set values of the fuse registers */
67+
writel(0xffffffff, vpu->ctrl_base + CTRL_G1_DEC_FUSE);
68+
writel(0xffffffff, vpu->ctrl_base + CTRL_G1_PP_FUSE);
69+
writel(0xffffffff, vpu->ctrl_base + CTRL_G2_DEC_FUSE);
70+
71+
clk_bulk_disable_unprepare(vpu->variant->num_clocks, vpu->clocks);
72+
73+
return 0;
74+
}
75+
76+
/*
77+
* Supported formats.
78+
*/
79+
80+
static const struct hantro_fmt imx8m_vpu_postproc_fmts[] = {
81+
{
82+
.fourcc = V4L2_PIX_FMT_YUYV,
83+
.codec_mode = HANTRO_MODE_NONE,
84+
},
85+
};
86+
87+
static const struct hantro_fmt imx8m_vpu_dec_fmts[] = {
88+
{
89+
.fourcc = V4L2_PIX_FMT_NV12,
90+
.codec_mode = HANTRO_MODE_NONE,
91+
},
92+
{
93+
.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
94+
.codec_mode = HANTRO_MODE_MPEG2_DEC,
95+
.max_depth = 2,
96+
.frmsize = {
97+
.min_width = 48,
98+
.max_width = 1920,
99+
.step_width = MB_DIM,
100+
.min_height = 48,
101+
.max_height = 1088,
102+
.step_height = MB_DIM,
103+
},
104+
},
105+
{
106+
.fourcc = V4L2_PIX_FMT_VP8_FRAME,
107+
.codec_mode = HANTRO_MODE_VP8_DEC,
108+
.max_depth = 2,
109+
.frmsize = {
110+
.min_width = 48,
111+
.max_width = 3840,
112+
.step_width = 16,
113+
.min_height = 48,
114+
.max_height = 2160,
115+
.step_height = 16,
116+
},
117+
},
118+
{
119+
.fourcc = V4L2_PIX_FMT_H264_SLICE,
120+
.codec_mode = HANTRO_MODE_H264_DEC,
121+
.max_depth = 2,
122+
.frmsize = {
123+
.min_width = 48,
124+
.max_width = 3840,
125+
.step_width = MB_DIM,
126+
.min_height = 48,
127+
.max_height = 2160,
128+
.step_height = MB_DIM,
129+
},
130+
},
131+
};
132+
133+
static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id)
134+
{
135+
struct hantro_dev *vpu = dev_id;
136+
enum vb2_buffer_state state;
137+
u32 status;
138+
139+
status = vdpu_read(vpu, G1_REG_INTERRUPT);
140+
state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ?
141+
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
142+
143+
vdpu_write(vpu, 0, G1_REG_INTERRUPT);
144+
vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
145+
146+
hantro_irq_done(vpu, 0, state);
147+
148+
return IRQ_HANDLED;
149+
}
150+
151+
static int imx8mq_vpu_hw_init(struct hantro_dev *vpu)
152+
{
153+
vpu->dec_base = vpu->reg_bases[0];
154+
vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1];
155+
156+
return 0;
157+
}
158+
159+
static void imx8m_vpu_g1_reset(struct hantro_ctx *ctx)
160+
{
161+
struct hantro_dev *vpu = ctx->dev;
162+
163+
imx8m_soft_reset(vpu, RESET_G1);
164+
}
165+
166+
/*
167+
* Supported codec ops.
168+
*/
169+
170+
static const struct hantro_codec_ops imx8mq_vpu_codec_ops[] = {
171+
[HANTRO_MODE_MPEG2_DEC] = {
172+
.run = hantro_g1_mpeg2_dec_run,
173+
.reset = imx8m_vpu_g1_reset,
174+
.init = hantro_mpeg2_dec_init,
175+
.exit = hantro_mpeg2_dec_exit,
176+
},
177+
[HANTRO_MODE_VP8_DEC] = {
178+
.run = hantro_g1_vp8_dec_run,
179+
.reset = imx8m_vpu_g1_reset,
180+
.init = hantro_vp8_dec_init,
181+
.exit = hantro_vp8_dec_exit,
182+
},
183+
[HANTRO_MODE_H264_DEC] = {
184+
.run = hantro_g1_h264_dec_run,
185+
.reset = imx8m_vpu_g1_reset,
186+
.init = hantro_h264_dec_init,
187+
.exit = hantro_h264_dec_exit,
188+
},
189+
};
190+
191+
/*
192+
* VPU variants.
193+
*/
194+
195+
static const struct hantro_irq imx8mq_irqs[] = {
196+
{ "g1", imx8m_vpu_g1_irq },
197+
{ "g2", NULL /* TODO: imx8m_vpu_g2_irq */ },
198+
};
199+
200+
static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" };
201+
static const char * const imx8mq_reg_names[] = { "g1", "g2", "ctrl" };
202+
203+
const struct hantro_variant imx8mq_vpu_variant = {
204+
.dec_fmts = imx8m_vpu_dec_fmts,
205+
.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
206+
.postproc_fmts = imx8m_vpu_postproc_fmts,
207+
.num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts),
208+
.postproc_regs = &hantro_g1_postproc_regs,
209+
.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
210+
HANTRO_H264_DECODER,
211+
.codec_ops = imx8mq_vpu_codec_ops,
212+
.init = imx8mq_vpu_hw_init,
213+
.runtime_resume = imx8mq_runtime_resume,
214+
.irqs = imx8mq_irqs,
215+
.num_irqs = ARRAY_SIZE(imx8mq_irqs),
216+
.clk_names = imx8mq_clk_names,
217+
.num_clocks = ARRAY_SIZE(imx8mq_clk_names),
218+
.reg_names = imx8mq_reg_names,
219+
.num_regs = ARRAY_SIZE(imx8mq_reg_names)
220+
};

0 commit comments

Comments
 (0)