File Index
Files and directories
Sign in
FILE

imx8m_vpu_hw.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/verisilicon/imx8m_vpu_hw.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Hantro VPU codec driver
  4 *
  5 * Copyright (C) 2019 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
  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#include "hantro_g2_regs.h"
 15
 16#define CTRL_SOFT_RESET		0x00
 17#define RESET_G1		BIT(1)
 18#define RESET_G2		BIT(0)
 19
 20#define CTRL_CLOCK_ENABLE	0x04
 21#define CLOCK_G1		BIT(1)
 22#define CLOCK_G2		BIT(0)
 23
 24#define CTRL_G1_DEC_FUSE	0x08
 25#define CTRL_G1_PP_FUSE		0x0c
 26#define CTRL_G2_DEC_FUSE	0x10
 27
 28static void imx8m_soft_reset(struct hantro_dev *vpu, u32 reset_bits)
 29{
 30	u32 val;
 31
 32	/* Assert */
 33	val = readl(vpu->ctrl_base + CTRL_SOFT_RESET);
 34	val &= ~reset_bits;
 35	writel(val, vpu->ctrl_base + CTRL_SOFT_RESET);
 36
 37	udelay(2);
 38
 39	/* Release */
 40	val = readl(vpu->ctrl_base + CTRL_SOFT_RESET);
 41	val |= reset_bits;
 42	writel(val, vpu->ctrl_base + CTRL_SOFT_RESET);
 43}
 44
 45static void imx8m_clk_enable(struct hantro_dev *vpu, u32 clock_bits)
 46{
 47	u32 val;
 48
 49	val = readl(vpu->ctrl_base + CTRL_CLOCK_ENABLE);
 50	val |= clock_bits;
 51	writel(val, vpu->ctrl_base + CTRL_CLOCK_ENABLE);
 52}
 53
 54static int imx8mq_runtime_resume(struct hantro_dev *vpu)
 55{
 56	int ret;
 57
 58	ret = clk_bulk_prepare_enable(vpu->variant->num_clocks, vpu->clocks);
 59	if (ret) {
 60		dev_err(vpu->dev, "Failed to enable clocks\n");
 61		return ret;
 62	}
 63
 64	imx8m_soft_reset(vpu, RESET_G1 | RESET_G2);
 65	imx8m_clk_enable(vpu, CLOCK_G1 | CLOCK_G2);
 66
 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);
 71
 72	clk_bulk_disable_unprepare(vpu->variant->num_clocks, vpu->clocks);
 73
 74	return 0;
 75}
 76
 77/*
 78 * Supported formats.
 79 */
 80
 81static const struct hantro_fmt imx8m_vpu_postproc_fmts[] = {
 82	{
 83		.fourcc = V4L2_PIX_FMT_YUYV,
 84		.codec_mode = HANTRO_MODE_NONE,
 85		.postprocessed = true,
 86		.frmsize = {
 87			.min_width = FMT_MIN_WIDTH,
 88			.max_width = FMT_UHD_WIDTH,
 89			.step_width = MB_DIM,
 90			.min_height = FMT_MIN_HEIGHT,
 91			.max_height = FMT_UHD_HEIGHT,
 92			.step_height = MB_DIM,
 93		},
 94	},
 95};
 96
 97static const struct hantro_fmt imx8m_vpu_dec_fmts[] = {
 98	{
 99		.fourcc = V4L2_PIX_FMT_NV12,
100		.codec_mode = HANTRO_MODE_NONE,
101		.frmsize = {
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,
108		},
109	},
110	{
111		.fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
112		.codec_mode = HANTRO_MODE_MPEG2_DEC,
113		.max_depth = 2,
114		.frmsize = {
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,
121		},
122	},
123	{
124		.fourcc = V4L2_PIX_FMT_VP8_FRAME,
125		.codec_mode = HANTRO_MODE_VP8_DEC,
126		.max_depth = 2,
127		.frmsize = {
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,
134		},
135	},
136	{
137		.fourcc = V4L2_PIX_FMT_H264_SLICE,
138		.codec_mode = HANTRO_MODE_H264_DEC,
139		.max_depth = 2,
140		.frmsize = {
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,
147		},
148	},
149};
150
151static const struct hantro_fmt imx8m_vpu_g2_postproc_fmts[] = {
152	{
153		.fourcc = V4L2_PIX_FMT_NV12,
154		.codec_mode = HANTRO_MODE_NONE,
155		.match_depth = true,
156		.postprocessed = true,
157		.frmsize = {
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,
164		},
165	},
166	{
167		.fourcc = V4L2_PIX_FMT_P010,
168		.codec_mode = HANTRO_MODE_NONE,
169		.match_depth = true,
170		.postprocessed = true,
171		.frmsize = {
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,
178		},
179	},
180};
181
182static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = {
183	{
184		.fourcc = V4L2_PIX_FMT_NV12_4L4,
185		.codec_mode = HANTRO_MODE_NONE,
186		.match_depth = true,
187		.frmsize = {
188			.min_width = FMT_MIN_WIDTH,
189			.max_width = FMT_UHD_WIDTH,
190			.step_width = 8,
191			.min_height = FMT_MIN_HEIGHT,
192			.max_height = FMT_UHD_HEIGHT,
193			.step_height = 32,
194		},
195	},
196	{
197		.fourcc = V4L2_PIX_FMT_NV15_4L4,
198		.codec_mode = HANTRO_MODE_NONE,
199		.match_depth = true,
200		.frmsize = {
201			.min_width = FMT_MIN_WIDTH,
202			.max_width = FMT_UHD_WIDTH,
203			.step_width = 8,
204			.min_height = FMT_MIN_HEIGHT,
205			.max_height = FMT_UHD_HEIGHT,
206			.step_height = 32,
207		},
208	},
209	{
210		.fourcc = V4L2_PIX_FMT_HEVC_SLICE,
211		.codec_mode = HANTRO_MODE_HEVC_DEC,
212		.max_depth = 2,
213		.frmsize = {
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,
220		},
221	},
222	{
223		.fourcc = V4L2_PIX_FMT_VP9_FRAME,
224		.codec_mode = HANTRO_MODE_VP9_DEC,
225		.max_depth = 2,
226		.frmsize = {
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,
233		},
234	},
235};
236
237static int imx8mq_vpu_hw_init(struct hantro_dev *vpu)
238{
239	vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1];
240
241	return 0;
242}
243
244static void imx8m_vpu_g1_reset(struct hantro_ctx *ctx)
245{
246	struct hantro_dev *vpu = ctx->dev;
247
248	imx8m_soft_reset(vpu, RESET_G1);
249}
250
251/*
252 * Supported codec ops.
253 */
254
255static const struct hantro_codec_ops imx8mq_vpu_codec_ops[] = {
256	[HANTRO_MODE_MPEG2_DEC] = {
257		.run = hantro_g1_mpeg2_dec_run,
258		.reset = imx8m_vpu_g1_reset,
259		.init = hantro_mpeg2_dec_init,
260		.exit = hantro_mpeg2_dec_exit,
261	},
262	[HANTRO_MODE_VP8_DEC] = {
263		.run = hantro_g1_vp8_dec_run,
264		.reset = imx8m_vpu_g1_reset,
265		.init = hantro_vp8_dec_init,
266		.exit = hantro_vp8_dec_exit,
267	},
268	[HANTRO_MODE_H264_DEC] = {
269		.run = hantro_g1_h264_dec_run,
270		.reset = imx8m_vpu_g1_reset,
271		.init = hantro_h264_dec_init,
272		.exit = hantro_h264_dec_exit,
273	},
274};
275
276static const struct hantro_codec_ops imx8mq_vpu_g1_codec_ops[] = {
277	[HANTRO_MODE_MPEG2_DEC] = {
278		.run = hantro_g1_mpeg2_dec_run,
279		.init = hantro_mpeg2_dec_init,
280		.exit = hantro_mpeg2_dec_exit,
281	},
282	[HANTRO_MODE_VP8_DEC] = {
283		.run = hantro_g1_vp8_dec_run,
284		.init = hantro_vp8_dec_init,
285		.exit = hantro_vp8_dec_exit,
286	},
287	[HANTRO_MODE_H264_DEC] = {
288		.run = hantro_g1_h264_dec_run,
289		.init = hantro_h264_dec_init,
290		.exit = hantro_h264_dec_exit,
291	},
292};
293
294static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = {
295	[HANTRO_MODE_HEVC_DEC] = {
296		.run = hantro_g2_hevc_dec_run,
297		.reset = hantro_g2_reset,
298		.init = hantro_hevc_dec_init,
299		.exit = hantro_hevc_dec_exit,
300	},
301	[HANTRO_MODE_VP9_DEC] = {
302		.run = hantro_g2_vp9_dec_run,
303		.reset = hantro_g2_reset,
304		.done = hantro_g2_vp9_dec_done,
305		.init = hantro_vp9_dec_init,
306		.exit = hantro_vp9_dec_exit,
307	},
308};
309
310/*
311 * VPU variants.
312 */
313
314static const struct hantro_irq imx8mq_irqs[] = {
315	{ "g1", hantro_g1_irq },
316};
317
318static const struct hantro_irq imx8mq_g2_irqs[] = {
319	{ "g2", hantro_g2_irq },
320};
321
322static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" };
323static const char * const imx8mq_reg_names[] = { "g1", "g2", "ctrl" };
324static const char * const imx8mq_g1_clk_names[] = { "g1" };
325static const char * const imx8mq_g2_clk_names[] = { "g2" };
326
327const struct hantro_variant imx8mq_vpu_variant = {
328	.dec_fmts = imx8m_vpu_dec_fmts,
329	.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
330	.postproc_fmts = imx8m_vpu_postproc_fmts,
331	.num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts),
332	.postproc_ops = &hantro_g1_postproc_ops,
333	.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
334		 HANTRO_H264_DECODER,
335	.codec_ops = imx8mq_vpu_codec_ops,
336	.init = imx8mq_vpu_hw_init,
337	.runtime_resume = imx8mq_runtime_resume,
338	.irqs = imx8mq_irqs,
339	.num_irqs = ARRAY_SIZE(imx8mq_irqs),
340	.clk_names = imx8mq_clk_names,
341	.num_clocks = ARRAY_SIZE(imx8mq_clk_names),
342	.reg_names = imx8mq_reg_names,
343	.num_regs = ARRAY_SIZE(imx8mq_reg_names)
344};
345
346static const struct of_device_id imx8mq_vpu_shared_resources[] = {
347	{ .compatible = "nxp,imx8mq-vpu-g1", },
348	{ .compatible = "nxp,imx8mq-vpu-g2", },
349	{ /* sentinel */ }
350};
351
352const struct hantro_variant imx8mq_vpu_g1_variant = {
353	.dec_fmts = imx8m_vpu_dec_fmts,
354	.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
355	.postproc_fmts = imx8m_vpu_postproc_fmts,
356	.num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts),
357	.postproc_ops = &hantro_g1_postproc_ops,
358	.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
359		 HANTRO_H264_DECODER,
360	.codec_ops = imx8mq_vpu_g1_codec_ops,
361	.irqs = imx8mq_irqs,
362	.num_irqs = ARRAY_SIZE(imx8mq_irqs),
363	.clk_names = imx8mq_g1_clk_names,
364	.num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),
365	.shared_devices = imx8mq_vpu_shared_resources,
366};
367
368const struct hantro_variant imx8mq_vpu_g2_variant = {
369	.dec_offset = 0x0,
370	.dec_fmts = imx8m_vpu_g2_dec_fmts,
371	.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_g2_dec_fmts),
372	.postproc_fmts = imx8m_vpu_g2_postproc_fmts,
373	.num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_g2_postproc_fmts),
374	.postproc_ops = &hantro_g2_postproc_ops,
375	.codec = HANTRO_HEVC_DECODER | HANTRO_VP9_DECODER,
376	.codec_ops = imx8mq_vpu_g2_codec_ops,
377	.irqs = imx8mq_g2_irqs,
378	.num_irqs = ARRAY_SIZE(imx8mq_g2_irqs),
379	.clk_names = imx8mq_g2_clk_names,
380	.num_clocks = ARRAY_SIZE(imx8mq_g2_clk_names),
381	.shared_devices = imx8mq_vpu_shared_resources,
382};
383
384const struct hantro_variant imx8mm_vpu_g1_variant = {
385	.dec_fmts = imx8m_vpu_dec_fmts,
386	.num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
387	.codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
388		 HANTRO_H264_DECODER,
389	.codec_ops = imx8mq_vpu_g1_codec_ops,
390	.irqs = imx8mq_irqs,
391	.num_irqs = ARRAY_SIZE(imx8mq_irqs),
392	.clk_names = imx8mq_g1_clk_names,
393	.num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),
394};
~/ Read-only file preview.