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 28 static 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 45 static 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 54 static 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 81 static 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 97 static 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 151 static const struct hantro_fmt imx8m_vpu_g2_postproc_fmts[] = { 152 { 153 .fourcc = V4L2_PIX_FMT_NV12, 154 .codec_mode = HANTRO_MODE_NONE, 155 .postprocessed = true, 156 .frmsize = { 157 .min_width = FMT_MIN_WIDTH, 158 .max_width = FMT_UHD_WIDTH, 159 .step_width = MB_DIM, 160 .min_height = FMT_MIN_HEIGHT, 161 .max_height = FMT_UHD_HEIGHT, 162 .step_height = MB_DIM, 163 }, 164 }, 165 { 166 .fourcc = V4L2_PIX_FMT_P010, 167 .codec_mode = HANTRO_MODE_NONE, 168 .postprocessed = true, 169 .frmsize = { 170 .min_width = FMT_MIN_WIDTH, 171 .max_width = FMT_UHD_WIDTH, 172 .step_width = MB_DIM, 173 .min_height = FMT_MIN_HEIGHT, 174 .max_height = FMT_UHD_HEIGHT, 175 .step_height = MB_DIM, 176 }, 177 }, 178 }; 179 180 static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = { 181 { 182 .fourcc = V4L2_PIX_FMT_NV12_4L4, 183 .codec_mode = HANTRO_MODE_NONE, 184 .match_depth = true, 185 .frmsize = { 186 .min_width = FMT_MIN_WIDTH, 187 .max_width = FMT_UHD_WIDTH, 188 .step_width = TILE_MB_DIM, 189 .min_height = FMT_MIN_HEIGHT, 190 .max_height = FMT_UHD_HEIGHT, 191 .step_height = TILE_MB_DIM, 192 }, 193 }, 194 { 195 .fourcc = V4L2_PIX_FMT_P010_4L4, 196 .codec_mode = HANTRO_MODE_NONE, 197 .match_depth = true, 198 .frmsize = { 199 .min_width = FMT_MIN_WIDTH, 200 .max_width = FMT_UHD_WIDTH, 201 .step_width = TILE_MB_DIM, 202 .min_height = FMT_MIN_HEIGHT, 203 .max_height = FMT_UHD_HEIGHT, 204 .step_height = TILE_MB_DIM, 205 }, 206 }, 207 { 208 .fourcc = V4L2_PIX_FMT_HEVC_SLICE, 209 .codec_mode = HANTRO_MODE_HEVC_DEC, 210 .max_depth = 2, 211 .frmsize = { 212 .min_width = FMT_MIN_WIDTH, 213 .max_width = FMT_UHD_WIDTH, 214 .step_width = TILE_MB_DIM, 215 .min_height = FMT_MIN_HEIGHT, 216 .max_height = FMT_UHD_HEIGHT, 217 .step_height = TILE_MB_DIM, 218 }, 219 }, 220 { 221 .fourcc = V4L2_PIX_FMT_VP9_FRAME, 222 .codec_mode = HANTRO_MODE_VP9_DEC, 223 .max_depth = 2, 224 .frmsize = { 225 .min_width = FMT_MIN_WIDTH, 226 .max_width = FMT_UHD_WIDTH, 227 .step_width = TILE_MB_DIM, 228 .min_height = FMT_MIN_HEIGHT, 229 .max_height = FMT_UHD_HEIGHT, 230 .step_height = TILE_MB_DIM, 231 }, 232 }, 233 }; 234 235 static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id) 236 { 237 struct hantro_dev *vpu = dev_id; 238 enum vb2_buffer_state state; 239 u32 status; 240 241 status = vdpu_read(vpu, G1_REG_INTERRUPT); 242 state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ? 243 VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; 244 245 vdpu_write(vpu, 0, G1_REG_INTERRUPT); 246 vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); 247 248 hantro_irq_done(vpu, state); 249 250 return IRQ_HANDLED; 251 } 252 253 static int imx8mq_vpu_hw_init(struct hantro_dev *vpu) 254 { 255 vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1]; 256 257 return 0; 258 } 259 260 static void imx8m_vpu_g1_reset(struct hantro_ctx *ctx) 261 { 262 struct hantro_dev *vpu = ctx->dev; 263 264 imx8m_soft_reset(vpu, RESET_G1); 265 } 266 267 /* 268 * Supported codec ops. 269 */ 270 271 static const struct hantro_codec_ops imx8mq_vpu_codec_ops[] = { 272 [HANTRO_MODE_MPEG2_DEC] = { 273 .run = hantro_g1_mpeg2_dec_run, 274 .reset = imx8m_vpu_g1_reset, 275 .init = hantro_mpeg2_dec_init, 276 .exit = hantro_mpeg2_dec_exit, 277 }, 278 [HANTRO_MODE_VP8_DEC] = { 279 .run = hantro_g1_vp8_dec_run, 280 .reset = imx8m_vpu_g1_reset, 281 .init = hantro_vp8_dec_init, 282 .exit = hantro_vp8_dec_exit, 283 }, 284 [HANTRO_MODE_H264_DEC] = { 285 .run = hantro_g1_h264_dec_run, 286 .reset = imx8m_vpu_g1_reset, 287 .init = hantro_h264_dec_init, 288 .exit = hantro_h264_dec_exit, 289 }, 290 }; 291 292 static const struct hantro_codec_ops imx8mq_vpu_g1_codec_ops[] = { 293 [HANTRO_MODE_MPEG2_DEC] = { 294 .run = hantro_g1_mpeg2_dec_run, 295 .init = hantro_mpeg2_dec_init, 296 .exit = hantro_mpeg2_dec_exit, 297 }, 298 [HANTRO_MODE_VP8_DEC] = { 299 .run = hantro_g1_vp8_dec_run, 300 .init = hantro_vp8_dec_init, 301 .exit = hantro_vp8_dec_exit, 302 }, 303 [HANTRO_MODE_H264_DEC] = { 304 .run = hantro_g1_h264_dec_run, 305 .init = hantro_h264_dec_init, 306 .exit = hantro_h264_dec_exit, 307 }, 308 }; 309 310 static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = { 311 [HANTRO_MODE_HEVC_DEC] = { 312 .run = hantro_g2_hevc_dec_run, 313 .init = hantro_hevc_dec_init, 314 .exit = hantro_hevc_dec_exit, 315 }, 316 [HANTRO_MODE_VP9_DEC] = { 317 .run = hantro_g2_vp9_dec_run, 318 .done = hantro_g2_vp9_dec_done, 319 .init = hantro_vp9_dec_init, 320 .exit = hantro_vp9_dec_exit, 321 }, 322 }; 323 324 /* 325 * VPU variants. 326 */ 327 328 static const struct hantro_irq imx8mq_irqs[] = { 329 { "g1", imx8m_vpu_g1_irq }, 330 }; 331 332 static const struct hantro_irq imx8mq_g2_irqs[] = { 333 { "g2", hantro_g2_irq }, 334 }; 335 336 static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" }; 337 static const char * const imx8mq_reg_names[] = { "g1", "g2", "ctrl" }; 338 static const char * const imx8mq_g1_clk_names[] = { "g1" }; 339 static const char * const imx8mq_g2_clk_names[] = { "g2" }; 340 341 const struct hantro_variant imx8mq_vpu_variant = { 342 .dec_fmts = imx8m_vpu_dec_fmts, 343 .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts), 344 .postproc_fmts = imx8m_vpu_postproc_fmts, 345 .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts), 346 .postproc_ops = &hantro_g1_postproc_ops, 347 .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | 348 HANTRO_H264_DECODER, 349 .codec_ops = imx8mq_vpu_codec_ops, 350 .init = imx8mq_vpu_hw_init, 351 .runtime_resume = imx8mq_runtime_resume, 352 .irqs = imx8mq_irqs, 353 .num_irqs = ARRAY_SIZE(imx8mq_irqs), 354 .clk_names = imx8mq_clk_names, 355 .num_clocks = ARRAY_SIZE(imx8mq_clk_names), 356 .reg_names = imx8mq_reg_names, 357 .num_regs = ARRAY_SIZE(imx8mq_reg_names) 358 }; 359 360 const struct hantro_variant imx8mq_vpu_g1_variant = { 361 .dec_fmts = imx8m_vpu_dec_fmts, 362 .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts), 363 .postproc_fmts = imx8m_vpu_postproc_fmts, 364 .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts), 365 .postproc_ops = &hantro_g1_postproc_ops, 366 .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | 367 HANTRO_H264_DECODER, 368 .codec_ops = imx8mq_vpu_g1_codec_ops, 369 .irqs = imx8mq_irqs, 370 .num_irqs = ARRAY_SIZE(imx8mq_irqs), 371 .clk_names = imx8mq_g1_clk_names, 372 .num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names), 373 }; 374 375 const struct hantro_variant imx8mq_vpu_g2_variant = { 376 .dec_offset = 0x0, 377 .dec_fmts = imx8m_vpu_g2_dec_fmts, 378 .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_g2_dec_fmts), 379 .postproc_fmts = imx8m_vpu_g2_postproc_fmts, 380 .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_g2_postproc_fmts), 381 .postproc_ops = &hantro_g2_postproc_ops, 382 .codec = HANTRO_HEVC_DECODER | HANTRO_VP9_DECODER, 383 .codec_ops = imx8mq_vpu_g2_codec_ops, 384 .irqs = imx8mq_g2_irqs, 385 .num_irqs = ARRAY_SIZE(imx8mq_g2_irqs), 386 .clk_names = imx8mq_g2_clk_names, 387 .num_clocks = ARRAY_SIZE(imx8mq_g2_clk_names), 388 }; 389 390 const struct hantro_variant imx8mm_vpu_g1_variant = { 391 .dec_fmts = imx8m_vpu_dec_fmts, 392 .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts), 393 .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | 394 HANTRO_H264_DECODER, 395 .codec_ops = imx8mq_vpu_g1_codec_ops, 396 .irqs = imx8mq_irqs, 397 .num_irqs = ARRAY_SIZE(imx8mq_irqs), 398 .clk_names = imx8mq_g1_clk_names, 399 .num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names), 400 }; 401