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