Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | /* SPDX-License-Identifier: GPL-2.0 */ /* * Hantro VPU codec driver * * Copyright 2018 Google LLC. * Tomasz Figa <tfiga@chromium.org> * * Based on s5p-mfc driver by Samsung Electronics Co., Ltd. * Copyright (C) 2011 Samsung Electronics Co., Ltd. */ #ifndef HANTRO_H_ #define HANTRO_H_ #include <linux/platform_device.h> #include <linux/videodev2.h> #include <linux/wait.h> #include <linux/clk.h> #include <linux/reset.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-mem2mem.h> #include <media/videobuf2-core.h> #include <media/videobuf2-dma-contig.h> #include "hantro_hw.h" struct hantro_ctx; struct hantro_codec_ops; struct hantro_postproc_ops; #define HANTRO_JPEG_ENCODER BIT(0) #define HANTRO_ENCODERS 0x0000ffff #define HANTRO_MPEG2_DECODER BIT(16) #define HANTRO_VP8_DECODER BIT(17) #define HANTRO_H264_DECODER BIT(18) #define HANTRO_HEVC_DECODER BIT(19) #define HANTRO_VP9_DECODER BIT(20) #define HANTRO_DECODERS 0xffff0000 /** * struct hantro_irq - irq handler and name * * @name: irq name for device tree lookup * @handler: interrupt handler */ struct hantro_irq { const char *name; irqreturn_t (*handler)(int irq, void *priv); }; /** * struct hantro_variant - information about VPU hardware variant * * @enc_offset: Offset from VPU base to encoder registers. * @dec_offset: Offset from VPU base to decoder registers. * @enc_fmts: Encoder formats. * @num_enc_fmts: Number of encoder formats. * @dec_fmts: Decoder formats. * @num_dec_fmts: Number of decoder formats. * @postproc_fmts: Post-processor formats. * @num_postproc_fmts: Number of post-processor formats. * @postproc_ops: Post-processor ops. * @codec: Supported codecs * @codec_ops: Codec ops. * @init: Initialize hardware, optional. * @runtime_resume: reenable hardware after power gating, optional. * @irqs: array of irq names and interrupt handlers * @num_irqs: number of irqs in the array * @clk_names: array of clock names * @num_clocks: number of clocks in the array * @reg_names: array of register range names * @num_regs: number of register range names in the array * @double_buffer: core needs double buffering * @legacy_regs: core uses legacy register set * @late_postproc: postproc must be set up at the end of the job */ struct hantro_variant { unsigned int enc_offset; unsigned int dec_offset; const struct hantro_fmt *enc_fmts; unsigned int num_enc_fmts; const struct hantro_fmt *dec_fmts; unsigned int num_dec_fmts; const struct hantro_fmt *postproc_fmts; unsigned int num_postproc_fmts; const struct hantro_postproc_ops *postproc_ops; unsigned int codec; const struct hantro_codec_ops *codec_ops; int (*init)(struct hantro_dev *vpu); int (*runtime_resume)(struct hantro_dev *vpu); const struct hantro_irq *irqs; int num_irqs; const char * const *clk_names; int num_clocks; const char * const *reg_names; int num_regs; unsigned int double_buffer : 1; unsigned int legacy_regs : 1; unsigned int late_postproc : 1; }; /** * enum hantro_codec_mode - codec operating mode. * @HANTRO_MODE_NONE: No operating mode. Used for RAW video formats. * @HANTRO_MODE_JPEG_ENC: JPEG encoder. * @HANTRO_MODE_H264_DEC: H264 decoder. * @HANTRO_MODE_MPEG2_DEC: MPEG-2 decoder. * @HANTRO_MODE_VP8_DEC: VP8 decoder. * @HANTRO_MODE_HEVC_DEC: HEVC decoder. * @HANTRO_MODE_VP9_DEC: VP9 decoder. */ enum hantro_codec_mode { HANTRO_MODE_NONE = -1, HANTRO_MODE_JPEG_ENC, HANTRO_MODE_H264_DEC, HANTRO_MODE_MPEG2_DEC, HANTRO_MODE_VP8_DEC, HANTRO_MODE_HEVC_DEC, HANTRO_MODE_VP9_DEC, }; /* * struct hantro_ctrl - helper type to declare supported controls * @codec: codec id this control belong to (HANTRO_JPEG_ENCODER, etc.) * @cfg: control configuration */ struct hantro_ctrl { unsigned int codec; struct v4l2_ctrl_config cfg; }; /* * struct hantro_func - Hantro VPU functionality * * @id: processing functionality ID (can be * %MEDIA_ENT_F_PROC_VIDEO_ENCODER or * %MEDIA_ENT_F_PROC_VIDEO_DECODER) * @vdev: &struct video_device that exposes the encoder or * decoder functionality * @source_pad: &struct media_pad with the source pad. * @sink: &struct media_entity pointer with the sink entity * @sink_pad: &struct media_pad with the sink pad. * @proc: &struct media_entity pointer with the M2M device itself. * @proc_pads: &struct media_pad with the @proc pads. * @intf_devnode: &struct media_intf devnode pointer with the interface * with controls the M2M device. * * Contains everything needed to attach the video device to the media device. */ struct hantro_func { unsigned int id; struct video_device vdev; struct media_pad source_pad; struct media_entity sink; struct media_pad sink_pad; struct media_entity proc; struct media_pad proc_pads[2]; struct media_intf_devnode *intf_devnode; }; static inline struct hantro_func * hantro_vdev_to_func(struct video_device *vdev) { return container_of(vdev, struct hantro_func, vdev); } /** * struct hantro_dev - driver data * @v4l2_dev: V4L2 device to register video devices for. * @m2m_dev: mem2mem device associated to this device. * @mdev: media device associated to this device. * @encoder: encoder functionality. * @decoder: decoder functionality. * @pdev: Pointer to VPU platform device. * @dev: Pointer to device for convenient logging using * dev_ macros. * @clocks: Array of clock handles. * @resets: Array of reset handles. * @reg_bases: Mapped addresses of VPU registers. * @enc_base: Mapped address of VPU encoder register for convenience. * @dec_base: Mapped address of VPU decoder register for convenience. * @ctrl_base: Mapped address of VPU control block. * @vpu_mutex: Mutex to synchronize V4L2 calls. * @irqlock: Spinlock to synchronize access to data structures * shared with interrupt handlers. * @variant: Hardware variant-specific parameters. * @watchdog_work: Delayed work for hardware timeout handling. */ struct hantro_dev { struct v4l2_device v4l2_dev; struct v4l2_m2m_dev *m2m_dev; struct media_device mdev; struct hantro_func *encoder; struct hantro_func *decoder; struct platform_device *pdev; struct device *dev; struct clk_bulk_data *clocks; struct reset_control *resets; void __iomem **reg_bases; void __iomem *enc_base; void __iomem *dec_base; void __iomem *ctrl_base; struct mutex vpu_mutex; /* video_device lock */ spinlock_t irqlock; const struct hantro_variant *variant; struct delayed_work watchdog_work; }; /** * struct hantro_ctx - Context (instance) private data. * * @dev: VPU driver data to which the context belongs. * @fh: V4L2 file handler. * @is_encoder: Decoder or encoder context? * * @sequence_cap: Sequence counter for capture queue * @sequence_out: Sequence counter for output queue * * @vpu_src_fmt: Descriptor of active source format. * @src_fmt: V4L2 pixel format of active source format. * @vpu_dst_fmt: Descriptor of active destination format. * @dst_fmt: V4L2 pixel format of active destination format. * * @ctrl_handler: Control handler used to register controls. * @jpeg_quality: User-specified JPEG compression quality. * @bit_depth: Bit depth of current frame * * @codec_ops: Set of operations related to codec mode. * @postproc: Post-processing context. * @h264_dec: H.264-decoding context. * @jpeg_enc: JPEG-encoding context. * @mpeg2_dec: MPEG-2-decoding context. * @vp8_dec: VP8-decoding context. * @hevc_dec: HEVC-decoding context. * @vp9_dec: VP9-decoding context. */ struct hantro_ctx { struct hantro_dev *dev; struct v4l2_fh fh; bool is_encoder; u32 sequence_cap; u32 sequence_out; const struct hantro_fmt *vpu_src_fmt; struct v4l2_pix_format_mplane src_fmt; const struct hantro_fmt *vpu_dst_fmt; struct v4l2_pix_format_mplane dst_fmt; struct v4l2_ctrl_handler ctrl_handler; int jpeg_quality; int bit_depth; const struct hantro_codec_ops *codec_ops; struct hantro_postproc_ctx postproc; /* Specific for particular codec modes. */ union { struct hantro_h264_dec_hw_ctx h264_dec; struct hantro_mpeg2_dec_hw_ctx mpeg2_dec; struct hantro_vp8_dec_hw_ctx vp8_dec; struct hantro_hevc_dec_hw_ctx hevc_dec; struct hantro_vp9_dec_hw_ctx vp9_dec; }; }; /** * struct hantro_fmt - information about supported video formats. * @name: Human readable name of the format. * @fourcc: FourCC code of the format. See V4L2_PIX_FMT_*. * @codec_mode: Codec mode related to this format. See * enum hantro_codec_mode. * @header_size: Optional header size. Currently used by JPEG encoder. * @max_depth: Maximum depth, for bitstream formats * @enc_fmt: Format identifier for encoder registers. * @frmsize: Supported range of frame sizes (only for bitstream formats). * @postprocessed: Indicates if this format needs the post-processor. * @match_depth: Indicates if format bit depth must match video bit depth */ struct hantro_fmt { char *name; u32 fourcc; enum hantro_codec_mode codec_mode; int header_size; int max_depth; enum hantro_enc_fmt enc_fmt; struct v4l2_frmsize_stepwise frmsize; bool postprocessed; bool match_depth; }; struct hantro_reg { u32 base; u32 shift; u32 mask; }; struct hantro_postproc_regs { struct hantro_reg pipeline_en; struct hantro_reg max_burst; struct hantro_reg clk_gate; struct hantro_reg out_swap32; struct hantro_reg out_endian; struct hantro_reg out_luma_base; struct hantro_reg input_width; struct hantro_reg input_height; struct hantro_reg output_width; struct hantro_reg output_height; struct hantro_reg input_fmt; struct hantro_reg output_fmt; struct hantro_reg orig_width; struct hantro_reg display_width; }; struct hantro_vp9_decoded_buffer_info { /* Info needed when the decoded frame serves as a reference frame. */ unsigned short width; unsigned short height; u32 bit_depth : 4; }; struct hantro_decoded_buffer { /* Must be the first field in this struct. */ struct v4l2_m2m_buffer base; union { struct hantro_vp9_decoded_buffer_info vp9; }; }; /* Logging helpers */ /** * DOC: hantro_debug: Module parameter to control level of debugging messages. * * Level of debugging messages can be controlled by bits of * module parameter called "debug". Meaning of particular * bits is as follows: * * bit 0 - global information: mode, size, init, release * bit 1 - each run start/result information * bit 2 - contents of small controls from userspace * bit 3 - contents of big controls from userspace * bit 4 - detail fmt, ctrl, buffer q/dq information * bit 5 - detail function enter/leave trace information * bit 6 - register write/read information */ extern int hantro_debug; #define vpu_debug(level, fmt, args...) \ do { \ if (hantro_debug & BIT(level)) \ pr_info("%s:%d: " fmt, \ __func__, __LINE__, ##args); \ } while (0) #define vpu_err(fmt, args...) \ pr_err("%s:%d: " fmt, __func__, __LINE__, ##args) /* Structure access helpers. */ static inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh) { return container_of(fh, struct hantro_ctx, fh); } /* Register accessors. */ static inline void vepu_write_relaxed(struct hantro_dev *vpu, u32 val, u32 reg) { vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val); writel_relaxed(val, vpu->enc_base + reg); } static inline void vepu_write(struct hantro_dev *vpu, u32 val, u32 reg) { vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val); writel(val, vpu->enc_base + reg); } static inline u32 vepu_read(struct hantro_dev *vpu, u32 reg) { u32 val = readl(vpu->enc_base + reg); vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val); return val; } static inline void vdpu_write_relaxed(struct hantro_dev *vpu, u32 val, u32 reg) { vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val); writel_relaxed(val, vpu->dec_base + reg); } static inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg) { vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val); writel(val, vpu->dec_base + reg); } static inline void hantro_write_addr(struct hantro_dev *vpu, unsigned long offset, dma_addr_t addr) { vdpu_write(vpu, addr & 0xffffffff, offset); } static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg) { u32 val = readl(vpu->dec_base + reg); vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val); return val; } static inline u32 vdpu_read_mask(struct hantro_dev *vpu, const struct hantro_reg *reg, u32 val) { u32 v; v = vdpu_read(vpu, reg->base); v &= ~(reg->mask << reg->shift); v |= ((val & reg->mask) << reg->shift); return v; } static inline void hantro_reg_write(struct hantro_dev *vpu, const struct hantro_reg *reg, u32 val) { vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base); } static inline void hantro_reg_write_s(struct hantro_dev *vpu, const struct hantro_reg *reg, u32 val) { vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base); } void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id); dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts); static inline struct vb2_v4l2_buffer * hantro_get_src_buf(struct hantro_ctx *ctx) { return v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); } static inline struct vb2_v4l2_buffer * hantro_get_dst_buf(struct hantro_ctx *ctx) { return v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); } bool hantro_needs_postproc(const struct hantro_ctx *ctx, const struct hantro_fmt *fmt); static inline dma_addr_t hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb) { if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) return ctx->postproc.dec_q[vb->index].dma; return vb2_dma_contig_plane_dma_addr(vb, 0); } static inline struct hantro_decoded_buffer * vb2_to_hantro_decoded_buf(struct vb2_buffer *buf) { return container_of(buf, struct hantro_decoded_buffer, base.vb.vb2_buf); } void hantro_postproc_disable(struct hantro_ctx *ctx); void hantro_postproc_enable(struct hantro_ctx *ctx); void hantro_postproc_free(struct hantro_ctx *ctx); int hantro_postproc_alloc(struct hantro_ctx *ctx); int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx, struct v4l2_frmsizeenum *fsize); #endif /* HANTRO_H_ */ |