/* SPDX-License-Identifier: GPL-2.0+ */ /* * NVIDIA Tegra Video decoder driver * * Copyright (C) 2016-2019 GRATE-DRIVER project */ #ifndef TEGRA_VDE_H #define TEGRA_VDE_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ICMDQUE_WR 0x00 #define CMDQUE_CONTROL 0x08 #define INTR_STATUS 0x18 #define BSE_INT_ENB 0x40 #define BSE_CONFIG 0x44 #define BSE_ICMDQUE_EMPTY BIT(3) #define BSE_DMA_BUSY BIT(23) #define BSEV_ALIGN SZ_1 #define FRAMEID_ALIGN SZ_256 #define SXE_BUFFER SZ_32K #define VDE_ATOM SZ_16 struct clk; struct dma_buf; struct gen_pool; struct tegra_ctx; struct iommu_group; struct iommu_domain; struct reset_control; struct dma_buf_attachment; struct tegra_vde_h264_frame; struct tegra_vde_h264_decoder_ctx; struct tegra_video_frame { struct dma_buf_attachment *y_dmabuf_attachment; struct dma_buf_attachment *cb_dmabuf_attachment; struct dma_buf_attachment *cr_dmabuf_attachment; struct dma_buf_attachment *aux_dmabuf_attachment; dma_addr_t y_addr; dma_addr_t cb_addr; dma_addr_t cr_addr; dma_addr_t aux_addr; u32 frame_num; u32 flags; u32 luma_atoms_pitch; u32 chroma_atoms_pitch; }; struct tegra_coded_fmt_desc { u32 fourcc; struct v4l2_frmsize_stepwise frmsize; unsigned int num_decoded_fmts; const u32 *decoded_fmts; int (*decode_run)(struct tegra_ctx *ctx); int (*decode_wait)(struct tegra_ctx *ctx); }; struct tegra_vde_soc { bool supports_ref_pic_marking; const struct tegra_coded_fmt_desc *coded_fmts; u32 num_coded_fmts; }; struct tegra_vde_bo { struct iova *iova; struct sg_table sgt; struct tegra_vde *vde; enum dma_data_direction dma_dir; unsigned long dma_attrs; dma_addr_t dma_handle; dma_addr_t dma_addr; void *dma_cookie; size_t size; }; struct tegra_vde { void __iomem *sxe; void __iomem *bsev; void __iomem *mbe; void __iomem *ppe; void __iomem *mce; void __iomem *tfe; void __iomem *ppb; void __iomem *vdma; void __iomem *frameid; struct device *dev; struct mutex lock; struct mutex map_lock; struct list_head map_list; struct reset_control *rst; struct reset_control *rst_mc; struct gen_pool *iram_pool; struct completion decode_completion; struct clk *clk; struct iommu_domain *domain; struct iommu_group *group; struct iova_domain iova; struct iova *iova_resv_static_addresses; struct iova *iova_resv_last_page; const struct tegra_vde_soc *soc; struct tegra_vde_bo *secure_bo; dma_addr_t bitstream_data_addr; dma_addr_t iram_lists_addr; u32 *iram; struct v4l2_device v4l2_dev; struct v4l2_m2m_dev *m2m; struct media_device mdev; struct video_device vdev; struct mutex v4l2_lock; struct workqueue_struct *wq; struct tegra_video_frame frames[V4L2_H264_NUM_DPB_ENTRIES + 1]; }; int tegra_vde_alloc_bo(struct tegra_vde *vde, struct tegra_vde_bo **ret_bo, enum dma_data_direction dma_dir, size_t size); void tegra_vde_free_bo(struct tegra_vde_bo *bo); struct tegra_ctx_h264 { const struct v4l2_ctrl_h264_decode_params *decode_params; const struct v4l2_ctrl_h264_sps *sps; const struct v4l2_ctrl_h264_pps *pps; }; struct tegra_ctx { struct tegra_vde *vde; struct tegra_ctx_h264 h264; struct work_struct work; struct v4l2_fh fh; struct v4l2_ctrl_handler hdl; struct v4l2_format coded_fmt; struct v4l2_format decoded_fmt; const struct tegra_coded_fmt_desc *coded_fmt_desc; struct v4l2_ctrl *ctrls[]; }; struct tegra_m2m_buffer { struct v4l2_m2m_buffer m2m; struct dma_buf_attachment *a[VB2_MAX_PLANES]; dma_addr_t dma_base[VB2_MAX_PLANES]; dma_addr_t dma_addr[VB2_MAX_PLANES]; struct iova *iova[VB2_MAX_PLANES]; struct tegra_vde_bo *aux; bool b_frame; }; static inline struct tegra_m2m_buffer * vb_to_tegra_buf(struct vb2_buffer *vb) { struct v4l2_m2m_buffer *m2m = container_of(vb, struct v4l2_m2m_buffer, vb.vb2_buf); return container_of(m2m, struct tegra_m2m_buffer, m2m); } void tegra_vde_prepare_control_data(struct tegra_ctx *ctx, u32 id); void tegra_vde_writel(struct tegra_vde *vde, u32 value, void __iomem *base, u32 offset); u32 tegra_vde_readl(struct tegra_vde *vde, void __iomem *base, u32 offset); void tegra_vde_set_bits(struct tegra_vde *vde, u32 mask, void __iomem *base, u32 offset); int tegra_vde_h264_decode_run(struct tegra_ctx *ctx); int tegra_vde_h264_decode_wait(struct tegra_ctx *ctx); int tegra_vde_iommu_init(struct tegra_vde *vde); void tegra_vde_iommu_deinit(struct tegra_vde *vde); int tegra_vde_iommu_map(struct tegra_vde *vde, struct sg_table *sgt, struct iova **iovap, size_t size); void tegra_vde_iommu_unmap(struct tegra_vde *vde, struct iova *iova); int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde, struct dma_buf *dmabuf, enum dma_data_direction dma_dir, struct dma_buf_attachment **ap, dma_addr_t *addrp); void tegra_vde_dmabuf_cache_unmap(struct tegra_vde *vde, struct dma_buf_attachment *a, bool release); void tegra_vde_dmabuf_cache_unmap_sync(struct tegra_vde *vde); void tegra_vde_dmabuf_cache_unmap_all(struct tegra_vde *vde); static __maybe_unused char const * tegra_vde_reg_base_name(struct tegra_vde *vde, void __iomem *base) { if (vde->sxe == base) return "SXE"; if (vde->bsev == base) return "BSEV"; if (vde->mbe == base) return "MBE"; if (vde->ppe == base) return "PPE"; if (vde->mce == base) return "MCE"; if (vde->tfe == base) return "TFE"; if (vde->ppb == base) return "PPB"; if (vde->vdma == base) return "VDMA"; if (vde->frameid == base) return "FRAMEID"; return "???"; } int tegra_vde_v4l2_init(struct tegra_vde *vde); void tegra_vde_v4l2_deinit(struct tegra_vde *vde); #endif /* TEGRA_VDE_H */