403 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Hantro VPU codec driver4 *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 0x0017#define RESET_G1 BIT(1)18#define RESET_G2 BIT(0)19 20#define CTRL_CLOCK_ENABLE 0x0421#define CLOCK_G1 BIT(1)22#define CLOCK_G2 BIT(0)23 24#define CTRL_G1_DEC_FUSE 0x0825#define CTRL_G1_PP_FUSE 0x0c26#define CTRL_G2_DEC_FUSE 0x1027 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 = TILE_MB_DIM,191 .min_height = FMT_MIN_HEIGHT,192 .max_height = FMT_UHD_HEIGHT,193 .step_height = TILE_MB_DIM,194 },195 },196 {197 .fourcc = V4L2_PIX_FMT_P010_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 = TILE_MB_DIM,204 .min_height = FMT_MIN_HEIGHT,205 .max_height = FMT_UHD_HEIGHT,206 .step_height = TILE_MB_DIM,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 irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id)238{239 struct hantro_dev *vpu = dev_id;240 enum vb2_buffer_state state;241 u32 status;242 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;246 247 vdpu_write(vpu, 0, G1_REG_INTERRUPT);248 vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);249 250 hantro_irq_done(vpu, state);251 252 return IRQ_HANDLED;253}254 255static int imx8mq_vpu_hw_init(struct hantro_dev *vpu)256{257 vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1];258 259 return 0;260}261 262static void imx8m_vpu_g1_reset(struct hantro_ctx *ctx)263{264 struct hantro_dev *vpu = ctx->dev;265 266 imx8m_soft_reset(vpu, RESET_G1);267}268 269/*270 * Supported codec ops.271 */272 273static 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,279 },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,285 },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,291 },292};293 294static 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,299 },300 [HANTRO_MODE_VP8_DEC] = {301 .run = hantro_g1_vp8_dec_run,302 .init = hantro_vp8_dec_init,303 .exit = hantro_vp8_dec_exit,304 },305 [HANTRO_MODE_H264_DEC] = {306 .run = hantro_g1_h264_dec_run,307 .init = hantro_h264_dec_init,308 .exit = hantro_h264_dec_exit,309 },310};311 312static 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,317 },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,323 },324};325 326/*327 * VPU variants.328 */329 330static const struct hantro_irq imx8mq_irqs[] = {331 { "g1", imx8m_vpu_g1_irq },332};333 334static const struct hantro_irq imx8mq_g2_irqs[] = {335 { "g2", hantro_g2_irq },336};337 338static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" };339static const char * const imx8mq_reg_names[] = { "g1", "g2", "ctrl" };340static const char * const imx8mq_g1_clk_names[] = { "g1" };341static const char * const imx8mq_g2_clk_names[] = { "g2" };342 343const 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 |350 HANTRO_H264_DECODER,351 .codec_ops = imx8mq_vpu_codec_ops,352 .init = imx8mq_vpu_hw_init,353 .runtime_resume = imx8mq_runtime_resume,354 .irqs = imx8mq_irqs,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)360};361 362const 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 |369 HANTRO_H264_DECODER,370 .codec_ops = imx8mq_vpu_g1_codec_ops,371 .irqs = imx8mq_irqs,372 .num_irqs = ARRAY_SIZE(imx8mq_irqs),373 .clk_names = imx8mq_g1_clk_names,374 .num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),375};376 377const struct hantro_variant imx8mq_vpu_g2_variant = {378 .dec_offset = 0x0,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),390};391 392const 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 |396 HANTRO_H264_DECODER,397 .codec_ops = imx8mq_vpu_g1_codec_ops,398 .irqs = imx8mq_irqs,399 .num_irqs = ARRAY_SIZE(imx8mq_irqs),400 .clk_names = imx8mq_g1_clk_names,401 .num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),402};403