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 .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 182 static 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 237 static 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 255 static 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 262 static 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 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, 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 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, 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 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, 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 330 static const struct hantro_irq imx8mq_irqs[] = { 331 { "g1", imx8m_vpu_g1_irq }, 332 }; 333 334 static const struct hantro_irq imx8mq_g2_irqs[] = { 335 { "g2", hantro_g2_irq }, 336 }; 337 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" }; 342 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 | 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 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 | 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 377 const 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 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 | 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