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 = 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 237 static 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 244 static 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 255 static 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 276 static 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 294 static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = { 295 [HANTRO_MODE_HEVC_DEC] = { 296 .run = hantro_g2_hevc_dec_run, 297 .init = hantro_hevc_dec_init, 298 .exit = hantro_hevc_dec_exit, 299 }, 300 [HANTRO_MODE_VP9_DEC] = { 301 .run = hantro_g2_vp9_dec_run, 302 .done = hantro_g2_vp9_dec_done, 303 .init = hantro_vp9_dec_init, 304 .exit = hantro_vp9_dec_exit, 305 }, 306 }; 307 308 /* 309 * VPU variants. 310 */ 311 312 static const struct hantro_irq imx8mq_irqs[] = { 313 { "g1", hantro_g1_irq }, 314 }; 315 316 static const struct hantro_irq imx8mq_g2_irqs[] = { 317 { "g2", hantro_g2_irq }, 318 }; 319 320 static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" }; 321 static const char * const imx8mq_reg_names[] = { "g1", "g2", "ctrl" }; 322 static const char * const imx8mq_g1_clk_names[] = { "g1" }; 323 static const char * const imx8mq_g2_clk_names[] = { "g2" }; 324 325 const struct hantro_variant imx8mq_vpu_variant = { 326 .dec_fmts = imx8m_vpu_dec_fmts, 327 .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts), 328 .postproc_fmts = imx8m_vpu_postproc_fmts, 329 .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts), 330 .postproc_ops = &hantro_g1_postproc_ops, 331 .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | 332 HANTRO_H264_DECODER, 333 .codec_ops = imx8mq_vpu_codec_ops, 334 .init = imx8mq_vpu_hw_init, 335 .runtime_resume = imx8mq_runtime_resume, 336 .irqs = imx8mq_irqs, 337 .num_irqs = ARRAY_SIZE(imx8mq_irqs), 338 .clk_names = imx8mq_clk_names, 339 .num_clocks = ARRAY_SIZE(imx8mq_clk_names), 340 .reg_names = imx8mq_reg_names, 341 .num_regs = ARRAY_SIZE(imx8mq_reg_names) 342 }; 343 344 const struct hantro_variant imx8mq_vpu_g1_variant = { 345 .dec_fmts = imx8m_vpu_dec_fmts, 346 .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts), 347 .postproc_fmts = imx8m_vpu_postproc_fmts, 348 .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts), 349 .postproc_ops = &hantro_g1_postproc_ops, 350 .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | 351 HANTRO_H264_DECODER, 352 .codec_ops = imx8mq_vpu_g1_codec_ops, 353 .irqs = imx8mq_irqs, 354 .num_irqs = ARRAY_SIZE(imx8mq_irqs), 355 .clk_names = imx8mq_g1_clk_names, 356 .num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names), 357 }; 358 359 const struct hantro_variant imx8mq_vpu_g2_variant = { 360 .dec_offset = 0x0, 361 .dec_fmts = imx8m_vpu_g2_dec_fmts, 362 .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_g2_dec_fmts), 363 .postproc_fmts = imx8m_vpu_g2_postproc_fmts, 364 .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_g2_postproc_fmts), 365 .postproc_ops = &hantro_g2_postproc_ops, 366 .codec = HANTRO_HEVC_DECODER | HANTRO_VP9_DECODER, 367 .codec_ops = imx8mq_vpu_g2_codec_ops, 368 .irqs = imx8mq_g2_irqs, 369 .num_irqs = ARRAY_SIZE(imx8mq_g2_irqs), 370 .clk_names = imx8mq_g2_clk_names, 371 .num_clocks = ARRAY_SIZE(imx8mq_g2_clk_names), 372 }; 373 374 const struct hantro_variant imx8mm_vpu_g1_variant = { 375 .dec_fmts = imx8m_vpu_dec_fmts, 376 .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts), 377 .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | 378 HANTRO_H264_DECODER, 379 .codec_ops = imx8mq_vpu_g1_codec_ops, 380 .irqs = imx8mq_irqs, 381 .num_irqs = ARRAY_SIZE(imx8mq_irqs), 382 .clk_names = imx8mq_g1_clk_names, 383 .num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names), 384 }; 385