1 // SPDX-License-Identifier: GPL-2.0
3 * Hantro VPU codec driver
5 * Copyright (C) 2019 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
9 #include <linux/delay.h>
12 #include "hantro_jpeg.h"
13 #include "hantro_g1_regs.h"
14 #include "hantro_g2_regs.h"
16 #define CTRL_SOFT_RESET 0x00
17 #define RESET_G1 BIT(1)
18 #define RESET_G2 BIT(0)
20 #define CTRL_CLOCK_ENABLE 0x04
21 #define CLOCK_G1 BIT(1)
22 #define CLOCK_G2 BIT(0)
24 #define CTRL_G1_DEC_FUSE 0x08
25 #define CTRL_G1_PP_FUSE 0x0c
26 #define CTRL_G2_DEC_FUSE 0x10
28 static void imx8m_soft_reset(struct hantro_dev
*vpu
, u32 reset_bits
)
33 val
= readl(vpu
->ctrl_base
+ CTRL_SOFT_RESET
);
35 writel(val
, vpu
->ctrl_base
+ CTRL_SOFT_RESET
);
40 val
= readl(vpu
->ctrl_base
+ CTRL_SOFT_RESET
);
42 writel(val
, vpu
->ctrl_base
+ CTRL_SOFT_RESET
);
45 static void imx8m_clk_enable(struct hantro_dev
*vpu
, u32 clock_bits
)
49 val
= readl(vpu
->ctrl_base
+ CTRL_CLOCK_ENABLE
);
51 writel(val
, vpu
->ctrl_base
+ CTRL_CLOCK_ENABLE
);
54 static int imx8mq_runtime_resume(struct hantro_dev
*vpu
)
58 ret
= clk_bulk_prepare_enable(vpu
->variant
->num_clocks
, vpu
->clocks
);
60 dev_err(vpu
->dev
, "Failed to enable clocks\n");
64 imx8m_soft_reset(vpu
, RESET_G1
| RESET_G2
);
65 imx8m_clk_enable(vpu
, CLOCK_G1
| CLOCK_G2
);
67 /* Set values of the fuse registers */
68 writel(0xffffffff, vpu
->ctrl_base
+ CTRL_G1_DEC_FUSE
);
69 writel(0xffffffff, vpu
->ctrl_base
+ CTRL_G1_PP_FUSE
);
70 writel(0xffffffff, vpu
->ctrl_base
+ CTRL_G2_DEC_FUSE
);
72 clk_bulk_disable_unprepare(vpu
->variant
->num_clocks
, vpu
->clocks
);
81 static const struct hantro_fmt imx8m_vpu_postproc_fmts
[] = {
83 .fourcc
= V4L2_PIX_FMT_YUYV
,
84 .codec_mode
= HANTRO_MODE_NONE
,
85 .postprocessed
= true,
87 .min_width
= FMT_MIN_WIDTH
,
88 .max_width
= FMT_UHD_WIDTH
,
90 .min_height
= FMT_MIN_HEIGHT
,
91 .max_height
= FMT_UHD_HEIGHT
,
92 .step_height
= MB_DIM
,
97 static const struct hantro_fmt imx8m_vpu_dec_fmts
[] = {
99 .fourcc
= V4L2_PIX_FMT_NV12
,
100 .codec_mode
= HANTRO_MODE_NONE
,
102 .min_width
= FMT_MIN_WIDTH
,
103 .max_width
= FMT_UHD_WIDTH
,
104 .step_width
= MB_DIM
,
105 .min_height
= FMT_MIN_HEIGHT
,
106 .max_height
= FMT_UHD_HEIGHT
,
107 .step_height
= MB_DIM
,
111 .fourcc
= V4L2_PIX_FMT_MPEG2_SLICE
,
112 .codec_mode
= HANTRO_MODE_MPEG2_DEC
,
115 .min_width
= FMT_MIN_WIDTH
,
116 .max_width
= FMT_FHD_WIDTH
,
117 .step_width
= MB_DIM
,
118 .min_height
= FMT_MIN_HEIGHT
,
119 .max_height
= FMT_FHD_HEIGHT
,
120 .step_height
= MB_DIM
,
124 .fourcc
= V4L2_PIX_FMT_VP8_FRAME
,
125 .codec_mode
= HANTRO_MODE_VP8_DEC
,
128 .min_width
= FMT_MIN_WIDTH
,
129 .max_width
= FMT_UHD_WIDTH
,
130 .step_width
= MB_DIM
,
131 .min_height
= FMT_MIN_HEIGHT
,
132 .max_height
= FMT_UHD_HEIGHT
,
133 .step_height
= MB_DIM
,
137 .fourcc
= V4L2_PIX_FMT_H264_SLICE
,
138 .codec_mode
= HANTRO_MODE_H264_DEC
,
141 .min_width
= FMT_MIN_WIDTH
,
142 .max_width
= FMT_UHD_WIDTH
,
143 .step_width
= MB_DIM
,
144 .min_height
= FMT_MIN_HEIGHT
,
145 .max_height
= FMT_UHD_HEIGHT
,
146 .step_height
= MB_DIM
,
151 static const struct hantro_fmt imx8m_vpu_g2_postproc_fmts
[] = {
153 .fourcc
= V4L2_PIX_FMT_NV12
,
154 .codec_mode
= HANTRO_MODE_NONE
,
156 .postprocessed
= true,
158 .min_width
= FMT_MIN_WIDTH
,
159 .max_width
= FMT_UHD_WIDTH
,
160 .step_width
= MB_DIM
,
161 .min_height
= FMT_MIN_HEIGHT
,
162 .max_height
= FMT_UHD_HEIGHT
,
163 .step_height
= MB_DIM
,
167 .fourcc
= V4L2_PIX_FMT_P010
,
168 .codec_mode
= HANTRO_MODE_NONE
,
170 .postprocessed
= true,
172 .min_width
= FMT_MIN_WIDTH
,
173 .max_width
= FMT_UHD_WIDTH
,
174 .step_width
= MB_DIM
,
175 .min_height
= FMT_MIN_HEIGHT
,
176 .max_height
= FMT_UHD_HEIGHT
,
177 .step_height
= MB_DIM
,
182 static const struct hantro_fmt imx8m_vpu_g2_dec_fmts
[] = {
184 .fourcc
= V4L2_PIX_FMT_NV12_4L4
,
185 .codec_mode
= HANTRO_MODE_NONE
,
188 .min_width
= FMT_MIN_WIDTH
,
189 .max_width
= FMT_UHD_WIDTH
,
191 .min_height
= FMT_MIN_HEIGHT
,
192 .max_height
= FMT_UHD_HEIGHT
,
197 .fourcc
= V4L2_PIX_FMT_NV15_4L4
,
198 .codec_mode
= HANTRO_MODE_NONE
,
201 .min_width
= FMT_MIN_WIDTH
,
202 .max_width
= FMT_UHD_WIDTH
,
204 .min_height
= FMT_MIN_HEIGHT
,
205 .max_height
= FMT_UHD_HEIGHT
,
210 .fourcc
= V4L2_PIX_FMT_HEVC_SLICE
,
211 .codec_mode
= HANTRO_MODE_HEVC_DEC
,
214 .min_width
= FMT_MIN_WIDTH
,
215 .max_width
= FMT_UHD_WIDTH
,
216 .step_width
= TILE_MB_DIM
,
217 .min_height
= FMT_MIN_HEIGHT
,
218 .max_height
= FMT_UHD_HEIGHT
,
219 .step_height
= TILE_MB_DIM
,
223 .fourcc
= V4L2_PIX_FMT_VP9_FRAME
,
224 .codec_mode
= HANTRO_MODE_VP9_DEC
,
227 .min_width
= FMT_MIN_WIDTH
,
228 .max_width
= FMT_UHD_WIDTH
,
229 .step_width
= TILE_MB_DIM
,
230 .min_height
= FMT_MIN_HEIGHT
,
231 .max_height
= FMT_UHD_HEIGHT
,
232 .step_height
= TILE_MB_DIM
,
237 static irqreturn_t
imx8m_vpu_g1_irq(int irq
, void *dev_id
)
239 struct hantro_dev
*vpu
= dev_id
;
240 enum vb2_buffer_state state
;
243 status
= vdpu_read(vpu
, G1_REG_INTERRUPT
);
244 state
= (status
& G1_REG_INTERRUPT_DEC_RDY_INT
) ?
245 VB2_BUF_STATE_DONE
: VB2_BUF_STATE_ERROR
;
247 vdpu_write(vpu
, 0, G1_REG_INTERRUPT
);
248 vdpu_write(vpu
, G1_REG_CONFIG_DEC_CLK_GATE_E
, G1_REG_CONFIG
);
250 hantro_irq_done(vpu
, state
);
255 static int imx8mq_vpu_hw_init(struct hantro_dev
*vpu
)
257 vpu
->ctrl_base
= vpu
->reg_bases
[vpu
->variant
->num_regs
- 1];
262 static void imx8m_vpu_g1_reset(struct hantro_ctx
*ctx
)
264 struct hantro_dev
*vpu
= ctx
->dev
;
266 imx8m_soft_reset(vpu
, RESET_G1
);
270 * Supported codec ops.
273 static const struct hantro_codec_ops imx8mq_vpu_codec_ops
[] = {
274 [HANTRO_MODE_MPEG2_DEC
] = {
275 .run
= hantro_g1_mpeg2_dec_run
,
276 .reset
= imx8m_vpu_g1_reset
,
277 .init
= hantro_mpeg2_dec_init
,
278 .exit
= hantro_mpeg2_dec_exit
,
280 [HANTRO_MODE_VP8_DEC
] = {
281 .run
= hantro_g1_vp8_dec_run
,
282 .reset
= imx8m_vpu_g1_reset
,
283 .init
= hantro_vp8_dec_init
,
284 .exit
= hantro_vp8_dec_exit
,
286 [HANTRO_MODE_H264_DEC
] = {
287 .run
= hantro_g1_h264_dec_run
,
288 .reset
= imx8m_vpu_g1_reset
,
289 .init
= hantro_h264_dec_init
,
290 .exit
= hantro_h264_dec_exit
,
294 static const struct hantro_codec_ops imx8mq_vpu_g1_codec_ops
[] = {
295 [HANTRO_MODE_MPEG2_DEC
] = {
296 .run
= hantro_g1_mpeg2_dec_run
,
297 .init
= hantro_mpeg2_dec_init
,
298 .exit
= hantro_mpeg2_dec_exit
,
300 [HANTRO_MODE_VP8_DEC
] = {
301 .run
= hantro_g1_vp8_dec_run
,
302 .init
= hantro_vp8_dec_init
,
303 .exit
= hantro_vp8_dec_exit
,
305 [HANTRO_MODE_H264_DEC
] = {
306 .run
= hantro_g1_h264_dec_run
,
307 .init
= hantro_h264_dec_init
,
308 .exit
= hantro_h264_dec_exit
,
312 static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops
[] = {
313 [HANTRO_MODE_HEVC_DEC
] = {
314 .run
= hantro_g2_hevc_dec_run
,
315 .init
= hantro_hevc_dec_init
,
316 .exit
= hantro_hevc_dec_exit
,
318 [HANTRO_MODE_VP9_DEC
] = {
319 .run
= hantro_g2_vp9_dec_run
,
320 .done
= hantro_g2_vp9_dec_done
,
321 .init
= hantro_vp9_dec_init
,
322 .exit
= hantro_vp9_dec_exit
,
330 static const struct hantro_irq imx8mq_irqs
[] = {
331 { "g1", imx8m_vpu_g1_irq
},
334 static const struct hantro_irq imx8mq_g2_irqs
[] = {
335 { "g2", hantro_g2_irq
},
338 static const char * const imx8mq_clk_names
[] = { "g1", "g2", "bus" };
339 static const char * const imx8mq_reg_names
[] = { "g1", "g2", "ctrl" };
340 static const char * const imx8mq_g1_clk_names
[] = { "g1" };
341 static const char * const imx8mq_g2_clk_names
[] = { "g2" };
343 const struct hantro_variant imx8mq_vpu_variant
= {
344 .dec_fmts
= imx8m_vpu_dec_fmts
,
345 .num_dec_fmts
= ARRAY_SIZE(imx8m_vpu_dec_fmts
),
346 .postproc_fmts
= imx8m_vpu_postproc_fmts
,
347 .num_postproc_fmts
= ARRAY_SIZE(imx8m_vpu_postproc_fmts
),
348 .postproc_ops
= &hantro_g1_postproc_ops
,
349 .codec
= HANTRO_MPEG2_DECODER
| HANTRO_VP8_DECODER
|
351 .codec_ops
= imx8mq_vpu_codec_ops
,
352 .init
= imx8mq_vpu_hw_init
,
353 .runtime_resume
= imx8mq_runtime_resume
,
355 .num_irqs
= ARRAY_SIZE(imx8mq_irqs
),
356 .clk_names
= imx8mq_clk_names
,
357 .num_clocks
= ARRAY_SIZE(imx8mq_clk_names
),
358 .reg_names
= imx8mq_reg_names
,
359 .num_regs
= ARRAY_SIZE(imx8mq_reg_names
)
362 const struct hantro_variant imx8mq_vpu_g1_variant
= {
363 .dec_fmts
= imx8m_vpu_dec_fmts
,
364 .num_dec_fmts
= ARRAY_SIZE(imx8m_vpu_dec_fmts
),
365 .postproc_fmts
= imx8m_vpu_postproc_fmts
,
366 .num_postproc_fmts
= ARRAY_SIZE(imx8m_vpu_postproc_fmts
),
367 .postproc_ops
= &hantro_g1_postproc_ops
,
368 .codec
= HANTRO_MPEG2_DECODER
| HANTRO_VP8_DECODER
|
370 .codec_ops
= imx8mq_vpu_g1_codec_ops
,
372 .num_irqs
= ARRAY_SIZE(imx8mq_irqs
),
373 .clk_names
= imx8mq_g1_clk_names
,
374 .num_clocks
= ARRAY_SIZE(imx8mq_g1_clk_names
),
377 const struct hantro_variant imx8mq_vpu_g2_variant
= {
379 .dec_fmts
= imx8m_vpu_g2_dec_fmts
,
380 .num_dec_fmts
= ARRAY_SIZE(imx8m_vpu_g2_dec_fmts
),
381 .postproc_fmts
= imx8m_vpu_g2_postproc_fmts
,
382 .num_postproc_fmts
= ARRAY_SIZE(imx8m_vpu_g2_postproc_fmts
),
383 .postproc_ops
= &hantro_g2_postproc_ops
,
384 .codec
= HANTRO_HEVC_DECODER
| HANTRO_VP9_DECODER
,
385 .codec_ops
= imx8mq_vpu_g2_codec_ops
,
386 .irqs
= imx8mq_g2_irqs
,
387 .num_irqs
= ARRAY_SIZE(imx8mq_g2_irqs
),
388 .clk_names
= imx8mq_g2_clk_names
,
389 .num_clocks
= ARRAY_SIZE(imx8mq_g2_clk_names
),
392 const struct hantro_variant imx8mm_vpu_g1_variant
= {
393 .dec_fmts
= imx8m_vpu_dec_fmts
,
394 .num_dec_fmts
= ARRAY_SIZE(imx8m_vpu_dec_fmts
),
395 .codec
= HANTRO_MPEG2_DECODER
| HANTRO_VP8_DECODER
|
397 .codec_ops
= imx8mq_vpu_g1_codec_ops
,
399 .num_irqs
= ARRAY_SIZE(imx8mq_irqs
),
400 .clk_names
= imx8mq_g1_clk_names
,
401 .num_clocks
= ARRAY_SIZE(imx8mq_g1_clk_names
),