1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Cedrus VPU driver
4 *
5 * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
6 * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
7 * Copyright (C) 2018 Bootlin
8 *
9 * Based on the vim2m driver, that is:
10 *
11 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
12 * Pawel Osciak, <pawel@osciak.com>
13 * Marek Szyprowski, <m.szyprowski@samsung.com>
14 */
15
16 #ifndef _CEDRUS_H_
17 #define _CEDRUS_H_
18
19 #include <media/v4l2-ctrls.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-mem2mem.h>
22 #include <media/videobuf2-v4l2.h>
23 #include <media/videobuf2-dma-contig.h>
24
25 #include <linux/iopoll.h>
26 #include <linux/platform_device.h>
27
28 #define CEDRUS_NAME "cedrus"
29
30 #define CEDRUS_CAPABILITY_UNTILED BIT(0)
31 #define CEDRUS_CAPABILITY_H265_DEC BIT(1)
32 #define CEDRUS_CAPABILITY_H264_DEC BIT(2)
33 #define CEDRUS_CAPABILITY_MPEG2_DEC BIT(3)
34 #define CEDRUS_CAPABILITY_VP8_DEC BIT(4)
35
36 enum cedrus_codec {
37 CEDRUS_CODEC_MPEG2,
38 CEDRUS_CODEC_H264,
39 CEDRUS_CODEC_H265,
40 CEDRUS_CODEC_VP8,
41 CEDRUS_CODEC_LAST,
42 };
43
44 enum cedrus_irq_status {
45 CEDRUS_IRQ_NONE,
46 CEDRUS_IRQ_ERROR,
47 CEDRUS_IRQ_OK,
48 };
49
50 enum cedrus_h264_pic_type {
51 CEDRUS_H264_PIC_TYPE_FRAME = 0,
52 CEDRUS_H264_PIC_TYPE_FIELD,
53 CEDRUS_H264_PIC_TYPE_MBAFF,
54 };
55
56 struct cedrus_control {
57 struct v4l2_ctrl_config cfg;
58 enum cedrus_codec codec;
59 };
60
61 struct cedrus_h264_run {
62 const struct v4l2_ctrl_h264_decode_params *decode_params;
63 const struct v4l2_ctrl_h264_pps *pps;
64 const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
65 const struct v4l2_ctrl_h264_slice_params *slice_params;
66 const struct v4l2_ctrl_h264_sps *sps;
67 const struct v4l2_ctrl_h264_pred_weights *pred_weights;
68 };
69
70 struct cedrus_mpeg2_run {
71 const struct v4l2_ctrl_mpeg2_sequence *sequence;
72 const struct v4l2_ctrl_mpeg2_picture *picture;
73 const struct v4l2_ctrl_mpeg2_quantisation *quantisation;
74 };
75
76 struct cedrus_h265_run {
77 const struct v4l2_ctrl_hevc_sps *sps;
78 const struct v4l2_ctrl_hevc_pps *pps;
79 const struct v4l2_ctrl_hevc_slice_params *slice_params;
80 const struct v4l2_ctrl_hevc_decode_params *decode_params;
81 };
82
83 struct cedrus_vp8_run {
84 const struct v4l2_ctrl_vp8_frame *frame_params;
85 };
86
87 struct cedrus_run {
88 struct vb2_v4l2_buffer *src;
89 struct vb2_v4l2_buffer *dst;
90
91 union {
92 struct cedrus_h264_run h264;
93 struct cedrus_mpeg2_run mpeg2;
94 struct cedrus_h265_run h265;
95 struct cedrus_vp8_run vp8;
96 };
97 };
98
99 struct cedrus_buffer {
100 struct v4l2_m2m_buffer m2m_buf;
101
102 union {
103 struct {
104 unsigned int position;
105 enum cedrus_h264_pic_type pic_type;
106 } h264;
107 } codec;
108 };
109
110 struct cedrus_ctx {
111 struct v4l2_fh fh;
112 struct cedrus_dev *dev;
113
114 struct v4l2_pix_format src_fmt;
115 struct v4l2_pix_format dst_fmt;
116 enum cedrus_codec current_codec;
117
118 struct v4l2_ctrl_handler hdl;
119 struct v4l2_ctrl **ctrls;
120
121 union {
122 struct {
123 void *mv_col_buf;
124 dma_addr_t mv_col_buf_dma;
125 ssize_t mv_col_buf_field_size;
126 ssize_t mv_col_buf_size;
127 void *pic_info_buf;
128 dma_addr_t pic_info_buf_dma;
129 ssize_t pic_info_buf_size;
130 void *neighbor_info_buf;
131 dma_addr_t neighbor_info_buf_dma;
132 void *deblk_buf;
133 dma_addr_t deblk_buf_dma;
134 ssize_t deblk_buf_size;
135 void *intra_pred_buf;
136 dma_addr_t intra_pred_buf_dma;
137 ssize_t intra_pred_buf_size;
138 } h264;
139 struct {
140 void *mv_col_buf;
141 dma_addr_t mv_col_buf_addr;
142 ssize_t mv_col_buf_size;
143 ssize_t mv_col_buf_unit_size;
144 void *neighbor_info_buf;
145 dma_addr_t neighbor_info_buf_addr;
146 } h265;
147 struct {
148 unsigned int last_frame_p_type;
149 unsigned int last_filter_type;
150 unsigned int last_sharpness_level;
151
152 u8 *entropy_probs_buf;
153 dma_addr_t entropy_probs_buf_dma;
154 } vp8;
155 } codec;
156 };
157
158 struct cedrus_dec_ops {
159 void (*irq_clear)(struct cedrus_ctx *ctx);
160 void (*irq_disable)(struct cedrus_ctx *ctx);
161 enum cedrus_irq_status (*irq_status)(struct cedrus_ctx *ctx);
162 void (*setup)(struct cedrus_ctx *ctx, struct cedrus_run *run);
163 int (*start)(struct cedrus_ctx *ctx);
164 void (*stop)(struct cedrus_ctx *ctx);
165 void (*trigger)(struct cedrus_ctx *ctx);
166 };
167
168 struct cedrus_variant {
169 unsigned int capabilities;
170 unsigned int mod_rate;
171 };
172
173 struct cedrus_dev {
174 struct v4l2_device v4l2_dev;
175 struct video_device vfd;
176 struct media_device mdev;
177 struct media_pad pad[2];
178 struct platform_device *pdev;
179 struct device *dev;
180 struct v4l2_m2m_dev *m2m_dev;
181 struct cedrus_dec_ops *dec_ops[CEDRUS_CODEC_LAST];
182
183 /* Device file mutex */
184 struct mutex dev_mutex;
185
186 void __iomem *base;
187
188 struct clk *mod_clk;
189 struct clk *ahb_clk;
190 struct clk *ram_clk;
191
192 struct reset_control *rstc;
193
194 unsigned int capabilities;
195 };
196
197 extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
198 extern struct cedrus_dec_ops cedrus_dec_ops_h264;
199 extern struct cedrus_dec_ops cedrus_dec_ops_h265;
200 extern struct cedrus_dec_ops cedrus_dec_ops_vp8;
201
cedrus_write(struct cedrus_dev * dev,u32 reg,u32 val)202 static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val)
203 {
204 writel(val, dev->base + reg);
205 }
206
cedrus_read(struct cedrus_dev * dev,u32 reg)207 static inline u32 cedrus_read(struct cedrus_dev *dev, u32 reg)
208 {
209 return readl(dev->base + reg);
210 }
211
cedrus_wait_for(struct cedrus_dev * dev,u32 reg,u32 flag)212 static inline u32 cedrus_wait_for(struct cedrus_dev *dev, u32 reg, u32 flag)
213 {
214 u32 value;
215
216 return readl_poll_timeout_atomic(dev->base + reg, value,
217 (value & flag) == 0, 10, 1000);
218 }
219
cedrus_buf_addr(struct vb2_buffer * buf,struct v4l2_pix_format * pix_fmt,unsigned int plane)220 static inline dma_addr_t cedrus_buf_addr(struct vb2_buffer *buf,
221 struct v4l2_pix_format *pix_fmt,
222 unsigned int plane)
223 {
224 dma_addr_t addr = vb2_dma_contig_plane_dma_addr(buf, 0);
225
226 return addr + (pix_fmt ? (dma_addr_t)pix_fmt->bytesperline *
227 pix_fmt->height * plane : 0);
228 }
229
cedrus_dst_buf_addr(struct cedrus_ctx * ctx,int index,unsigned int plane)230 static inline dma_addr_t cedrus_dst_buf_addr(struct cedrus_ctx *ctx,
231 int index, unsigned int plane)
232 {
233 struct vb2_buffer *buf = NULL;
234 struct vb2_queue *vq;
235
236 if (index < 0)
237 return 0;
238
239 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
240 if (vq)
241 buf = vb2_get_buffer(vq, index);
242
243 return buf ? cedrus_buf_addr(buf, &ctx->dst_fmt, plane) : 0;
244 }
245
246 static inline struct cedrus_buffer *
vb2_v4l2_to_cedrus_buffer(const struct vb2_v4l2_buffer * p)247 vb2_v4l2_to_cedrus_buffer(const struct vb2_v4l2_buffer *p)
248 {
249 return container_of(p, struct cedrus_buffer, m2m_buf.vb);
250 }
251
252 static inline struct cedrus_buffer *
vb2_to_cedrus_buffer(const struct vb2_buffer * p)253 vb2_to_cedrus_buffer(const struct vb2_buffer *p)
254 {
255 return vb2_v4l2_to_cedrus_buffer(to_vb2_v4l2_buffer(p));
256 }
257
258 void *cedrus_find_control_data(struct cedrus_ctx *ctx, u32 id);
259
260 #endif
261