summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/tegra/vde/vde.h
blob: 0fbb1f3d2c88abbfb905caf38073d23e91affd50 (plain)
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
/* 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 <linux/completion.h>
#include <linux/dma-direction.h>
#include <linux/iova.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/workqueue.h>

#include <media/media-device.h>
#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-dma-sg.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>

#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 */