1
2
3#include <linux/atomic.h>
4#include <linux/bitfield.h>
5#include <linux/clk.h>
6#include <linux/delay.h>
7#include <linux/device.h>
8#include <linux/dma-mapping.h>
9#include <linux/interrupt.h>
10#include <linux/jiffies.h>
11#include <linux/module.h>
12#include <linux/mutex.h>
13#include <linux/of.h>
14#include <linux/of_irq.h>
15#include <linux/of_reserved_mem.h>
16#include <linux/platform_device.h>
17#include <linux/sched.h>
18#include <linux/spinlock.h>
19#include <linux/string.h>
20#include <linux/v4l2-controls.h>
21#include <linux/videodev2.h>
22#include <linux/wait.h>
23#include <linux/workqueue.h>
24#include <media/v4l2-ctrls.h>
25#include <media/v4l2-dev.h>
26#include <media/v4l2-device.h>
27#include <media/v4l2-dv-timings.h>
28#include <media/v4l2-event.h>
29#include <media/v4l2-ioctl.h>
30#include <media/videobuf2-dma-contig.h>
31
32#define DEVICE_NAME "aspeed-video"
33
34#define ASPEED_VIDEO_JPEG_NUM_QUALITIES 12
35#define ASPEED_VIDEO_JPEG_HEADER_SIZE 10
36#define ASPEED_VIDEO_JPEG_QUANT_SIZE 116
37#define ASPEED_VIDEO_JPEG_DCT_SIZE 34
38
39#define MAX_FRAME_RATE 60
40#define MAX_HEIGHT 1200
41#define MAX_WIDTH 1920
42#define MIN_HEIGHT 480
43#define MIN_WIDTH 640
44
45#define NUM_POLARITY_CHECKS 10
46#define INVALID_RESOLUTION_RETRIES 2
47#define INVALID_RESOLUTION_DELAY msecs_to_jiffies(250)
48#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(500)
49#define MODE_DETECT_TIMEOUT msecs_to_jiffies(500)
50#define STOP_TIMEOUT msecs_to_jiffies(1000)
51#define DIRECT_FETCH_THRESHOLD 0x0c0000
52
53#define VE_MAX_SRC_BUFFER_SIZE 0x8ca000
54#define VE_JPEG_HEADER_SIZE 0x006000
55
56#define VE_PROTECTION_KEY 0x000
57#define VE_PROTECTION_KEY_UNLOCK 0x1a038aa8
58
59#define VE_SEQ_CTRL 0x004
60#define VE_SEQ_CTRL_TRIG_MODE_DET BIT(0)
61#define VE_SEQ_CTRL_TRIG_CAPTURE BIT(1)
62#define VE_SEQ_CTRL_FORCE_IDLE BIT(2)
63#define VE_SEQ_CTRL_MULT_FRAME BIT(3)
64#define VE_SEQ_CTRL_TRIG_COMP BIT(4)
65#define VE_SEQ_CTRL_AUTO_COMP BIT(5)
66#define VE_SEQ_CTRL_EN_WATCHDOG BIT(7)
67#define VE_SEQ_CTRL_YUV420 BIT(10)
68#define VE_SEQ_CTRL_COMP_FMT GENMASK(11, 10)
69#define VE_SEQ_CTRL_HALT BIT(12)
70#define VE_SEQ_CTRL_EN_WATCHDOG_COMP BIT(14)
71#define VE_SEQ_CTRL_TRIG_JPG BIT(15)
72#define VE_SEQ_CTRL_CAP_BUSY BIT(16)
73#define VE_SEQ_CTRL_COMP_BUSY BIT(18)
74
75#ifdef CONFIG_MACH_ASPEED_G5
76#define VE_SEQ_CTRL_JPEG_MODE BIT(13)
77#else
78#define VE_SEQ_CTRL_JPEG_MODE BIT(8)
79#endif
80
81#define VE_CTRL 0x008
82#define VE_CTRL_HSYNC_POL BIT(0)
83#define VE_CTRL_VSYNC_POL BIT(1)
84#define VE_CTRL_SOURCE BIT(2)
85#define VE_CTRL_INT_DE BIT(4)
86#define VE_CTRL_DIRECT_FETCH BIT(5)
87#define VE_CTRL_YUV BIT(6)
88#define VE_CTRL_RGB BIT(7)
89#define VE_CTRL_CAPTURE_FMT GENMASK(7, 6)
90#define VE_CTRL_AUTO_OR_CURSOR BIT(8)
91#define VE_CTRL_CLK_INVERSE BIT(11)
92#define VE_CTRL_CLK_DELAY GENMASK(11, 9)
93#define VE_CTRL_INTERLACE BIT(14)
94#define VE_CTRL_HSYNC_POL_CTRL BIT(15)
95#define VE_CTRL_FRC GENMASK(23, 16)
96
97#define VE_TGS_0 0x00c
98#define VE_TGS_1 0x010
99#define VE_TGS_FIRST GENMASK(28, 16)
100#define VE_TGS_LAST GENMASK(12, 0)
101
102#define VE_SCALING_FACTOR 0x014
103#define VE_SCALING_FILTER0 0x018
104#define VE_SCALING_FILTER1 0x01c
105#define VE_SCALING_FILTER2 0x020
106#define VE_SCALING_FILTER3 0x024
107
108#define VE_CAP_WINDOW 0x030
109#define VE_COMP_WINDOW 0x034
110#define VE_COMP_PROC_OFFSET 0x038
111#define VE_COMP_OFFSET 0x03c
112#define VE_JPEG_ADDR 0x040
113#define VE_SRC0_ADDR 0x044
114#define VE_SRC_SCANLINE_OFFSET 0x048
115#define VE_SRC1_ADDR 0x04c
116#define VE_COMP_ADDR 0x054
117
118#define VE_STREAM_BUF_SIZE 0x058
119#define VE_STREAM_BUF_SIZE_N_PACKETS GENMASK(5, 3)
120#define VE_STREAM_BUF_SIZE_P_SIZE GENMASK(2, 0)
121
122#define VE_COMP_CTRL 0x060
123#define VE_COMP_CTRL_VQ_DCT_ONLY BIT(0)
124#define VE_COMP_CTRL_VQ_4COLOR BIT(1)
125#define VE_COMP_CTRL_QUANTIZE BIT(2)
126#define VE_COMP_CTRL_EN_BQ BIT(4)
127#define VE_COMP_CTRL_EN_CRYPTO BIT(5)
128#define VE_COMP_CTRL_DCT_CHR GENMASK(10, 6)
129#define VE_COMP_CTRL_DCT_LUM GENMASK(15, 11)
130#define VE_COMP_CTRL_EN_HQ BIT(16)
131#define VE_COMP_CTRL_RSVD BIT(19)
132#define VE_COMP_CTRL_ENCODE GENMASK(21, 20)
133#define VE_COMP_CTRL_HQ_DCT_CHR GENMASK(26, 22)
134#define VE_COMP_CTRL_HQ_DCT_LUM GENMASK(31, 27)
135
136#define VE_OFFSET_COMP_STREAM 0x078
137
138#define VE_SRC_LR_EDGE_DET 0x090
139#define VE_SRC_LR_EDGE_DET_LEFT GENMASK(11, 0)
140#define VE_SRC_LR_EDGE_DET_NO_V BIT(12)
141#define VE_SRC_LR_EDGE_DET_NO_H BIT(13)
142#define VE_SRC_LR_EDGE_DET_NO_DISP BIT(14)
143#define VE_SRC_LR_EDGE_DET_NO_CLK BIT(15)
144#define VE_SRC_LR_EDGE_DET_RT_SHF 16
145#define VE_SRC_LR_EDGE_DET_RT GENMASK(27, VE_SRC_LR_EDGE_DET_RT_SHF)
146#define VE_SRC_LR_EDGE_DET_INTERLACE BIT(31)
147
148#define VE_SRC_TB_EDGE_DET 0x094
149#define VE_SRC_TB_EDGE_DET_TOP GENMASK(12, 0)
150#define VE_SRC_TB_EDGE_DET_BOT_SHF 16
151#define VE_SRC_TB_EDGE_DET_BOT GENMASK(28, VE_SRC_TB_EDGE_DET_BOT_SHF)
152
153#define VE_MODE_DETECT_STATUS 0x098
154#define VE_MODE_DETECT_H_PIXELS GENMASK(11, 0)
155#define VE_MODE_DETECT_V_LINES_SHF 16
156#define VE_MODE_DETECT_V_LINES GENMASK(27, VE_MODE_DETECT_V_LINES_SHF)
157#define VE_MODE_DETECT_STATUS_VSYNC BIT(28)
158#define VE_MODE_DETECT_STATUS_HSYNC BIT(29)
159
160#define VE_SYNC_STATUS 0x09c
161#define VE_SYNC_STATUS_HSYNC GENMASK(11, 0)
162#define VE_SYNC_STATUS_VSYNC_SHF 16
163#define VE_SYNC_STATUS_VSYNC GENMASK(27, VE_SYNC_STATUS_VSYNC_SHF)
164
165#define VE_INTERRUPT_CTRL 0x304
166#define VE_INTERRUPT_STATUS 0x308
167#define VE_INTERRUPT_MODE_DETECT_WD BIT(0)
168#define VE_INTERRUPT_CAPTURE_COMPLETE BIT(1)
169#define VE_INTERRUPT_COMP_READY BIT(2)
170#define VE_INTERRUPT_COMP_COMPLETE BIT(3)
171#define VE_INTERRUPT_MODE_DETECT BIT(4)
172#define VE_INTERRUPT_FRAME_COMPLETE BIT(5)
173#define VE_INTERRUPT_DECODE_ERR BIT(6)
174#define VE_INTERRUPT_HALT_READY BIT(8)
175#define VE_INTERRUPT_HANG_WD BIT(9)
176#define VE_INTERRUPT_STREAM_DESC BIT(10)
177#define VE_INTERRUPT_VSYNC_DESC BIT(11)
178
179#define VE_MODE_DETECT 0x30c
180#define VE_MEM_RESTRICT_START 0x310
181#define VE_MEM_RESTRICT_END 0x314
182
183enum {
184 VIDEO_MODE_DETECT_DONE,
185 VIDEO_RES_CHANGE,
186 VIDEO_RES_DETECT,
187 VIDEO_STREAMING,
188 VIDEO_FRAME_INPRG,
189 VIDEO_STOPPED,
190 VIDEO_CLOCKS_ON,
191};
192
193struct aspeed_video_addr {
194 unsigned int size;
195 dma_addr_t dma;
196 void *virt;
197};
198
199struct aspeed_video_buffer {
200 struct vb2_v4l2_buffer vb;
201 struct list_head link;
202};
203
204#define to_aspeed_video_buffer(x) \
205 container_of((x), struct aspeed_video_buffer, vb)
206
207struct aspeed_video {
208 void __iomem *base;
209 struct clk *eclk;
210 struct clk *vclk;
211
212 struct device *dev;
213 struct v4l2_ctrl_handler ctrl_handler;
214 struct v4l2_device v4l2_dev;
215 struct v4l2_pix_format pix_fmt;
216 struct v4l2_bt_timings active_timings;
217 struct v4l2_bt_timings detected_timings;
218 u32 v4l2_input_status;
219 struct vb2_queue queue;
220 struct video_device vdev;
221 struct mutex video_lock;
222
223 wait_queue_head_t wait;
224 spinlock_t lock;
225 struct delayed_work res_work;
226 struct list_head buffers;
227 unsigned long flags;
228 unsigned int sequence;
229
230 unsigned int max_compressed_size;
231 struct aspeed_video_addr srcs[2];
232 struct aspeed_video_addr jpeg;
233
234 bool yuv420;
235 unsigned int frame_rate;
236 unsigned int jpeg_quality;
237
238 unsigned int frame_bottom;
239 unsigned int frame_left;
240 unsigned int frame_right;
241 unsigned int frame_top;
242};
243
244#define to_aspeed_video(x) container_of((x), struct aspeed_video, v4l2_dev)
245
246static const u32 aspeed_video_jpeg_header[ASPEED_VIDEO_JPEG_HEADER_SIZE] = {
247 0xe0ffd8ff, 0x464a1000, 0x01004649, 0x60000101, 0x00006000, 0x0f00feff,
248 0x00002d05, 0x00000000, 0x00000000, 0x00dbff00
249};
250
251static const u32 aspeed_video_jpeg_quant[ASPEED_VIDEO_JPEG_QUANT_SIZE] = {
252 0x081100c0, 0x00000000, 0x00110103, 0x03011102, 0xc4ff0111, 0x00001f00,
253 0x01010501, 0x01010101, 0x00000000, 0x00000000, 0x04030201, 0x08070605,
254 0xff0b0a09, 0x10b500c4, 0x03010200, 0x03040203, 0x04040505, 0x7d010000,
255 0x00030201, 0x12051104, 0x06413121, 0x07615113, 0x32147122, 0x08a19181,
256 0xc1b14223, 0xf0d15215, 0x72623324, 0x160a0982, 0x1a191817, 0x28272625,
257 0x35342a29, 0x39383736, 0x4544433a, 0x49484746, 0x5554534a, 0x59585756,
258 0x6564635a, 0x69686766, 0x7574736a, 0x79787776, 0x8584837a, 0x89888786,
259 0x9493928a, 0x98979695, 0xa3a29a99, 0xa7a6a5a4, 0xb2aaa9a8, 0xb6b5b4b3,
260 0xbab9b8b7, 0xc5c4c3c2, 0xc9c8c7c6, 0xd4d3d2ca, 0xd8d7d6d5, 0xe2e1dad9,
261 0xe6e5e4e3, 0xeae9e8e7, 0xf4f3f2f1, 0xf8f7f6f5, 0xc4fffaf9, 0x00011f00,
262 0x01010103, 0x01010101, 0x00000101, 0x00000000, 0x04030201, 0x08070605,
263 0xff0b0a09, 0x11b500c4, 0x02010200, 0x04030404, 0x04040507, 0x77020100,
264 0x03020100, 0x21050411, 0x41120631, 0x71610751, 0x81322213, 0x91421408,
265 0x09c1b1a1, 0xf0523323, 0xd1726215, 0x3424160a, 0x17f125e1, 0x261a1918,
266 0x2a292827, 0x38373635, 0x44433a39, 0x48474645, 0x54534a49, 0x58575655,
267 0x64635a59, 0x68676665, 0x74736a69, 0x78777675, 0x83827a79, 0x87868584,
268 0x928a8988, 0x96959493, 0x9a999897, 0xa5a4a3a2, 0xa9a8a7a6, 0xb4b3b2aa,
269 0xb8b7b6b5, 0xc3c2bab9, 0xc7c6c5c4, 0xd2cac9c8, 0xd6d5d4d3, 0xdad9d8d7,
270 0xe5e4e3e2, 0xe9e8e7e6, 0xf4f3f2ea, 0xf8f7f6f5, 0xdafffaf9, 0x01030c00,
271 0x03110200, 0x003f0011
272};
273
274static const u32 aspeed_video_jpeg_dct[ASPEED_VIDEO_JPEG_NUM_QUALITIES]
275 [ASPEED_VIDEO_JPEG_DCT_SIZE] = {
276 { 0x0d140043, 0x0c0f110f, 0x11101114, 0x17141516, 0x1e20321e,
277 0x3d1e1b1b, 0x32242e2b, 0x4b4c3f48, 0x44463f47, 0x61735a50,
278 0x566c5550, 0x88644644, 0x7a766c65, 0x4d808280, 0x8c978d60,
279 0x7e73967d, 0xdbff7b80, 0x1f014300, 0x272d2121, 0x3030582d,
280 0x697bb958, 0xb8b9b97b, 0xb9b8a6a6, 0xb9b9b9b9, 0xb9b9b9b9,
281 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9,
282 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xffb9b9b9 },
283 { 0x0c110043, 0x0a0d0f0d, 0x0f0e0f11, 0x14111213, 0x1a1c2b1a,
284 0x351a1818, 0x2b1f2826, 0x4142373f, 0x3c3d373e, 0x55644e46,
285 0x4b5f4a46, 0x77573d3c, 0x6b675f58, 0x43707170, 0x7a847b54,
286 0x6e64836d, 0xdbff6c70, 0x1b014300, 0x22271d1d, 0x2a2a4c27,
287 0x5b6ba04c, 0xa0a0a06b, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0,
288 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0,
289 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xffa0a0a0 },
290 { 0x090e0043, 0x090a0c0a, 0x0c0b0c0e, 0x110e0f10, 0x15172415,
291 0x2c151313, 0x241a211f, 0x36372e34, 0x31322e33, 0x4653413a,
292 0x3e4e3d3a, 0x62483231, 0x58564e49, 0x385d5e5d, 0x656d6645,
293 0x5b536c5a, 0xdbff595d, 0x16014300, 0x1c201818, 0x22223f20,
294 0x4b58853f, 0x85858558, 0x85858585, 0x85858585, 0x85858585,
295 0x85858585, 0x85858585, 0x85858585, 0x85858585, 0x85858585,
296 0x85858585, 0x85858585, 0x85858585, 0xff858585 },
297 { 0x070b0043, 0x07080a08, 0x0a090a0b, 0x0d0b0c0c, 0x11121c11,
298 0x23110f0f, 0x1c141a19, 0x2b2b2429, 0x27282428, 0x3842332e,
299 0x313e302e, 0x4e392827, 0x46443e3a, 0x2c4a4a4a, 0x50565137,
300 0x48425647, 0xdbff474a, 0x12014300, 0x161a1313, 0x1c1c331a,
301 0x3d486c33, 0x6c6c6c48, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c,
302 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c,
303 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0xff6c6c6c },
304 { 0x06090043, 0x05060706, 0x07070709, 0x0a09090a, 0x0d0e160d,
305 0x1b0d0c0c, 0x16101413, 0x21221c20, 0x1e1f1c20, 0x2b332824,
306 0x26302624, 0x3d2d1f1e, 0x3735302d, 0x22393a39, 0x3f443f2b,
307 0x38334338, 0xdbff3739, 0x0d014300, 0x11130e0e, 0x15152613,
308 0x2d355026, 0x50505035, 0x50505050, 0x50505050, 0x50505050,
309 0x50505050, 0x50505050, 0x50505050, 0x50505050, 0x50505050,
310 0x50505050, 0x50505050, 0x50505050, 0xff505050 },
311 { 0x04060043, 0x03040504, 0x05040506, 0x07060606, 0x09090f09,
312 0x12090808, 0x0f0a0d0d, 0x16161315, 0x14151315, 0x1d221b18,
313 0x19201918, 0x281e1514, 0x2423201e, 0x17262726, 0x2a2d2a1c,
314 0x25222d25, 0xdbff2526, 0x09014300, 0x0b0d0a0a, 0x0e0e1a0d,
315 0x1f25371a, 0x37373725, 0x37373737, 0x37373737, 0x37373737,
316 0x37373737, 0x37373737, 0x37373737, 0x37373737, 0x37373737,
317 0x37373737, 0x37373737, 0x37373737, 0xff373737 },
318 { 0x02030043, 0x01020202, 0x02020203, 0x03030303, 0x04040704,
319 0x09040404, 0x07050606, 0x0b0b090a, 0x0a0a090a, 0x0e110d0c,
320 0x0c100c0c, 0x140f0a0a, 0x1211100f, 0x0b131313, 0x1516150e,
321 0x12111612, 0xdbff1213, 0x04014300, 0x05060505, 0x07070d06,
322 0x0f121b0d, 0x1b1b1b12, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b,
323 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b,
324 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0xff1b1b1b },
325 { 0x01020043, 0x01010101, 0x01010102, 0x02020202, 0x03030503,
326 0x06030202, 0x05030404, 0x07070607, 0x06070607, 0x090b0908,
327 0x080a0808, 0x0d0a0706, 0x0c0b0a0a, 0x070c0d0c, 0x0e0f0e09,
328 0x0c0b0f0c, 0xdbff0c0c, 0x03014300, 0x03040303, 0x04040804,
329 0x0a0c1208, 0x1212120c, 0x12121212, 0x12121212, 0x12121212,
330 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212,
331 0x12121212, 0x12121212, 0x12121212, 0xff121212 },
332 { 0x01020043, 0x01010101, 0x01010102, 0x02020202, 0x03030503,
333 0x06030202, 0x05030404, 0x07070607, 0x06070607, 0x090b0908,
334 0x080a0808, 0x0d0a0706, 0x0c0b0a0a, 0x070c0d0c, 0x0e0f0e09,
335 0x0c0b0f0c, 0xdbff0c0c, 0x02014300, 0x03030202, 0x04040703,
336 0x080a0f07, 0x0f0f0f0a, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f,
337 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f,
338 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xff0f0f0f },
339 { 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x02020302,
340 0x04020202, 0x03020303, 0x05050405, 0x05050405, 0x07080606,
341 0x06080606, 0x0a070505, 0x09080807, 0x05090909, 0x0a0b0a07,
342 0x09080b09, 0xdbff0909, 0x02014300, 0x02030202, 0x03030503,
343 0x07080c05, 0x0c0c0c08, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
344 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
345 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xff0c0c0c },
346 { 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x01010201,
347 0x03010101, 0x02010202, 0x03030303, 0x03030303, 0x04050404,
348 0x04050404, 0x06050303, 0x06050505, 0x03060606, 0x07070704,
349 0x06050706, 0xdbff0606, 0x01014300, 0x01020101, 0x02020402,
350 0x05060904, 0x09090906, 0x09090909, 0x09090909, 0x09090909,
351 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909,
352 0x09090909, 0x09090909, 0x09090909, 0xff090909 },
353 { 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x01010101,
354 0x01010101, 0x01010101, 0x01010101, 0x01010101, 0x02020202,
355 0x02020202, 0x03020101, 0x03020202, 0x01030303, 0x03030302,
356 0x03020303, 0xdbff0403, 0x01014300, 0x01010101, 0x01010201,
357 0x03040602, 0x06060604, 0x06060606, 0x06060606, 0x06060606,
358 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
359 0x06060606, 0x06060606, 0x06060606, 0xff060606 }
360};
361
362static const struct v4l2_dv_timings_cap aspeed_video_timings_cap = {
363 .type = V4L2_DV_BT_656_1120,
364 .bt = {
365 .min_width = MIN_WIDTH,
366 .max_width = MAX_WIDTH,
367 .min_height = MIN_HEIGHT,
368 .max_height = MAX_HEIGHT,
369 .min_pixelclock = 6574080,
370 .max_pixelclock = 138240000,
371 .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
372 V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,
373 .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
374 V4L2_DV_BT_CAP_REDUCED_BLANKING |
375 V4L2_DV_BT_CAP_CUSTOM,
376 },
377};
378
379static void aspeed_video_init_jpeg_table(u32 *table, bool yuv420)
380{
381 int i;
382 unsigned int base;
383
384 for (i = 0; i < ASPEED_VIDEO_JPEG_NUM_QUALITIES; i++) {
385 base = 256 * i;
386 memcpy(&table[base], aspeed_video_jpeg_header,
387 sizeof(aspeed_video_jpeg_header));
388
389 base += ASPEED_VIDEO_JPEG_HEADER_SIZE;
390 memcpy(&table[base], aspeed_video_jpeg_dct[i],
391 sizeof(aspeed_video_jpeg_dct[i]));
392
393 base += ASPEED_VIDEO_JPEG_DCT_SIZE;
394 memcpy(&table[base], aspeed_video_jpeg_quant,
395 sizeof(aspeed_video_jpeg_quant));
396
397 if (yuv420)
398 table[base + 2] = 0x00220103;
399 }
400}
401
402static void aspeed_video_update(struct aspeed_video *video, u32 reg, u32 clear,
403 u32 bits)
404{
405 u32 t = readl(video->base + reg);
406 u32 before = t;
407
408 t &= ~clear;
409 t |= bits;
410 writel(t, video->base + reg);
411 dev_dbg(video->dev, "update %03x[%08x -> %08x]\n", reg, before,
412 readl(video->base + reg));
413}
414
415static u32 aspeed_video_read(struct aspeed_video *video, u32 reg)
416{
417 u32 t = readl(video->base + reg);
418
419 dev_dbg(video->dev, "read %03x[%08x]\n", reg, t);
420 return t;
421}
422
423static void aspeed_video_write(struct aspeed_video *video, u32 reg, u32 val)
424{
425 writel(val, video->base + reg);
426 dev_dbg(video->dev, "write %03x[%08x]\n", reg,
427 readl(video->base + reg));
428}
429
430static int aspeed_video_start_frame(struct aspeed_video *video)
431{
432 dma_addr_t addr;
433 unsigned long flags;
434 struct aspeed_video_buffer *buf;
435 u32 seq_ctrl = aspeed_video_read(video, VE_SEQ_CTRL);
436
437 if (video->v4l2_input_status) {
438 dev_dbg(video->dev, "No signal; don't start frame\n");
439 return 0;
440 }
441
442 if (!(seq_ctrl & VE_SEQ_CTRL_COMP_BUSY) ||
443 !(seq_ctrl & VE_SEQ_CTRL_CAP_BUSY)) {
444 dev_dbg(video->dev, "Engine busy; don't start frame\n");
445 return -EBUSY;
446 }
447
448 spin_lock_irqsave(&video->lock, flags);
449 buf = list_first_entry_or_null(&video->buffers,
450 struct aspeed_video_buffer, link);
451 if (!buf) {
452 spin_unlock_irqrestore(&video->lock, flags);
453 dev_dbg(video->dev, "No buffers; don't start frame\n");
454 return -EPROTO;
455 }
456
457 set_bit(VIDEO_FRAME_INPRG, &video->flags);
458 addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
459 spin_unlock_irqrestore(&video->lock, flags);
460
461 aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);
462 aspeed_video_write(video, VE_COMP_OFFSET, 0);
463 aspeed_video_write(video, VE_COMP_ADDR, addr);
464
465 aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
466 VE_INTERRUPT_COMP_COMPLETE);
467
468 aspeed_video_update(video, VE_SEQ_CTRL, 0,
469 VE_SEQ_CTRL_TRIG_CAPTURE | VE_SEQ_CTRL_TRIG_COMP);
470
471 return 0;
472}
473
474static void aspeed_video_enable_mode_detect(struct aspeed_video *video)
475{
476
477 aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
478 VE_INTERRUPT_MODE_DETECT);
479
480
481 aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_TRIG_MODE_DET);
482}
483
484static void aspeed_video_off(struct aspeed_video *video)
485{
486 if (!test_bit(VIDEO_CLOCKS_ON, &video->flags))
487 return;
488
489
490 aspeed_video_write(video, VE_INTERRUPT_CTRL, 0);
491 aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);
492
493
494 clk_disable(video->vclk);
495 clk_disable(video->eclk);
496
497 clear_bit(VIDEO_CLOCKS_ON, &video->flags);
498}
499
500static void aspeed_video_on(struct aspeed_video *video)
501{
502 if (test_bit(VIDEO_CLOCKS_ON, &video->flags))
503 return;
504
505
506 clk_enable(video->eclk);
507 clk_enable(video->vclk);
508
509 set_bit(VIDEO_CLOCKS_ON, &video->flags);
510}
511
512static void aspeed_video_bufs_done(struct aspeed_video *video,
513 enum vb2_buffer_state state)
514{
515 unsigned long flags;
516 struct aspeed_video_buffer *buf;
517
518 spin_lock_irqsave(&video->lock, flags);
519 list_for_each_entry(buf, &video->buffers, link)
520 vb2_buffer_done(&buf->vb.vb2_buf, state);
521 INIT_LIST_HEAD(&video->buffers);
522 spin_unlock_irqrestore(&video->lock, flags);
523}
524
525static void aspeed_video_irq_res_change(struct aspeed_video *video, ulong delay)
526{
527 dev_dbg(video->dev, "Resolution changed; resetting\n");
528
529 set_bit(VIDEO_RES_CHANGE, &video->flags);
530 clear_bit(VIDEO_FRAME_INPRG, &video->flags);
531
532 aspeed_video_off(video);
533 aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);
534
535 schedule_delayed_work(&video->res_work, delay);
536}
537
538static irqreturn_t aspeed_video_irq(int irq, void *arg)
539{
540 struct aspeed_video *video = arg;
541 u32 sts = aspeed_video_read(video, VE_INTERRUPT_STATUS);
542
543
544
545
546
547 if (sts & VE_INTERRUPT_MODE_DETECT_WD) {
548 aspeed_video_irq_res_change(video, 0);
549 return IRQ_HANDLED;
550 }
551
552 if (sts & VE_INTERRUPT_MODE_DETECT) {
553 if (test_bit(VIDEO_RES_DETECT, &video->flags)) {
554 aspeed_video_update(video, VE_INTERRUPT_CTRL,
555 VE_INTERRUPT_MODE_DETECT, 0);
556 aspeed_video_write(video, VE_INTERRUPT_STATUS,
557 VE_INTERRUPT_MODE_DETECT);
558 sts &= ~VE_INTERRUPT_MODE_DETECT;
559 set_bit(VIDEO_MODE_DETECT_DONE, &video->flags);
560 wake_up_interruptible_all(&video->wait);
561 } else {
562
563
564
565
566 aspeed_video_irq_res_change(video,
567 RESOLUTION_CHANGE_DELAY);
568 return IRQ_HANDLED;
569 }
570 }
571
572 if (sts & VE_INTERRUPT_COMP_COMPLETE) {
573 struct aspeed_video_buffer *buf;
574 u32 frame_size = aspeed_video_read(video,
575 VE_OFFSET_COMP_STREAM);
576
577 spin_lock(&video->lock);
578 clear_bit(VIDEO_FRAME_INPRG, &video->flags);
579 buf = list_first_entry_or_null(&video->buffers,
580 struct aspeed_video_buffer,
581 link);
582 if (buf) {
583 vb2_set_plane_payload(&buf->vb.vb2_buf, 0, frame_size);
584
585 if (!list_is_last(&buf->link, &video->buffers)) {
586 buf->vb.vb2_buf.timestamp = ktime_get_ns();
587 buf->vb.sequence = video->sequence++;
588 buf->vb.field = V4L2_FIELD_NONE;
589 vb2_buffer_done(&buf->vb.vb2_buf,
590 VB2_BUF_STATE_DONE);
591 list_del(&buf->link);
592 }
593 }
594 spin_unlock(&video->lock);
595
596 aspeed_video_update(video, VE_SEQ_CTRL,
597 VE_SEQ_CTRL_TRIG_CAPTURE |
598 VE_SEQ_CTRL_FORCE_IDLE |
599 VE_SEQ_CTRL_TRIG_COMP, 0);
600 aspeed_video_update(video, VE_INTERRUPT_CTRL,
601 VE_INTERRUPT_COMP_COMPLETE, 0);
602 aspeed_video_write(video, VE_INTERRUPT_STATUS,
603 VE_INTERRUPT_COMP_COMPLETE);
604 sts &= ~VE_INTERRUPT_COMP_COMPLETE;
605 if (test_bit(VIDEO_STREAMING, &video->flags) && buf)
606 aspeed_video_start_frame(video);
607 }
608
609 return sts ? IRQ_NONE : IRQ_HANDLED;
610}
611
612static void aspeed_video_check_and_set_polarity(struct aspeed_video *video)
613{
614 int i;
615 int hsync_counter = 0;
616 int vsync_counter = 0;
617 u32 sts;
618
619 for (i = 0; i < NUM_POLARITY_CHECKS; ++i) {
620 sts = aspeed_video_read(video, VE_MODE_DETECT_STATUS);
621 if (sts & VE_MODE_DETECT_STATUS_VSYNC)
622 vsync_counter--;
623 else
624 vsync_counter++;
625
626 if (sts & VE_MODE_DETECT_STATUS_HSYNC)
627 hsync_counter--;
628 else
629 hsync_counter++;
630 }
631
632 if (hsync_counter < 0 || vsync_counter < 0) {
633 u32 ctrl;
634
635 if (hsync_counter < 0) {
636 ctrl = VE_CTRL_HSYNC_POL;
637 video->detected_timings.polarities &=
638 ~V4L2_DV_HSYNC_POS_POL;
639 } else {
640 video->detected_timings.polarities |=
641 V4L2_DV_HSYNC_POS_POL;
642 }
643
644 if (vsync_counter < 0) {
645 ctrl = VE_CTRL_VSYNC_POL;
646 video->detected_timings.polarities &=
647 ~V4L2_DV_VSYNC_POS_POL;
648 } else {
649 video->detected_timings.polarities |=
650 V4L2_DV_VSYNC_POS_POL;
651 }
652
653 aspeed_video_update(video, VE_CTRL, 0, ctrl);
654 }
655}
656
657static bool aspeed_video_alloc_buf(struct aspeed_video *video,
658 struct aspeed_video_addr *addr,
659 unsigned int size)
660{
661 addr->virt = dma_alloc_coherent(video->dev, size, &addr->dma,
662 GFP_KERNEL);
663 if (!addr->virt)
664 return false;
665
666 addr->size = size;
667 return true;
668}
669
670static void aspeed_video_free_buf(struct aspeed_video *video,
671 struct aspeed_video_addr *addr)
672{
673 dma_free_coherent(video->dev, addr->size, addr->virt, addr->dma);
674 addr->size = 0;
675 addr->dma = 0ULL;
676 addr->virt = NULL;
677}
678
679
680
681
682
683
684
685static void aspeed_video_calc_compressed_size(struct aspeed_video *video,
686 unsigned int frame_size)
687{
688 int i, j;
689 u32 compression_buffer_size_reg = 0;
690 unsigned int size;
691 const unsigned int num_compression_packets = 4;
692 const unsigned int compression_packet_size = 1024;
693 const unsigned int max_compressed_size = frame_size / 2;
694
695 video->max_compressed_size = UINT_MAX;
696
697 for (i = 0; i < 6; ++i) {
698 for (j = 0; j < 8; ++j) {
699 size = (num_compression_packets << i) *
700 (compression_packet_size << j);
701 if (size < max_compressed_size)
702 continue;
703
704 if (size < video->max_compressed_size) {
705 compression_buffer_size_reg = (i << 3) | j;
706 video->max_compressed_size = size;
707 }
708 }
709 }
710
711 aspeed_video_write(video, VE_STREAM_BUF_SIZE,
712 compression_buffer_size_reg);
713
714 dev_dbg(video->dev, "Max compressed size: %x\n",
715 video->max_compressed_size);
716}
717
718#define res_check(v) test_and_clear_bit(VIDEO_MODE_DETECT_DONE, &(v)->flags)
719
720static void aspeed_video_get_resolution(struct aspeed_video *video)
721{
722 bool invalid_resolution = true;
723 int rc;
724 int tries = 0;
725 u32 mds;
726 u32 src_lr_edge;
727 u32 src_tb_edge;
728 u32 sync;
729 struct v4l2_bt_timings *det = &video->detected_timings;
730
731 det->width = MIN_WIDTH;
732 det->height = MIN_HEIGHT;
733 video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
734
735 do {
736 if (tries) {
737 set_current_state(TASK_INTERRUPTIBLE);
738 if (schedule_timeout(INVALID_RESOLUTION_DELAY))
739 return;
740 }
741
742 set_bit(VIDEO_RES_DETECT, &video->flags);
743 aspeed_video_enable_mode_detect(video);
744
745 rc = wait_event_interruptible_timeout(video->wait,
746 res_check(video),
747 MODE_DETECT_TIMEOUT);
748 if (!rc) {
749 dev_dbg(video->dev, "Timed out; first mode detect\n");
750 clear_bit(VIDEO_RES_DETECT, &video->flags);
751 return;
752 }
753
754
755 aspeed_video_update(video, VE_SEQ_CTRL,
756 VE_SEQ_CTRL_TRIG_MODE_DET, 0);
757
758 aspeed_video_check_and_set_polarity(video);
759
760 aspeed_video_enable_mode_detect(video);
761
762 rc = wait_event_interruptible_timeout(video->wait,
763 res_check(video),
764 MODE_DETECT_TIMEOUT);
765 clear_bit(VIDEO_RES_DETECT, &video->flags);
766 if (!rc) {
767 dev_dbg(video->dev, "Timed out; second mode detect\n");
768 return;
769 }
770
771 src_lr_edge = aspeed_video_read(video, VE_SRC_LR_EDGE_DET);
772 src_tb_edge = aspeed_video_read(video, VE_SRC_TB_EDGE_DET);
773 mds = aspeed_video_read(video, VE_MODE_DETECT_STATUS);
774 sync = aspeed_video_read(video, VE_SYNC_STATUS);
775
776 video->frame_bottom = (src_tb_edge & VE_SRC_TB_EDGE_DET_BOT) >>
777 VE_SRC_TB_EDGE_DET_BOT_SHF;
778 video->frame_top = src_tb_edge & VE_SRC_TB_EDGE_DET_TOP;
779 det->vfrontporch = video->frame_top;
780 det->vbackporch = ((mds & VE_MODE_DETECT_V_LINES) >>
781 VE_MODE_DETECT_V_LINES_SHF) - video->frame_bottom;
782 det->vsync = (sync & VE_SYNC_STATUS_VSYNC) >>
783 VE_SYNC_STATUS_VSYNC_SHF;
784 if (video->frame_top > video->frame_bottom)
785 continue;
786
787 video->frame_right = (src_lr_edge & VE_SRC_LR_EDGE_DET_RT) >>
788 VE_SRC_LR_EDGE_DET_RT_SHF;
789 video->frame_left = src_lr_edge & VE_SRC_LR_EDGE_DET_LEFT;
790 det->hfrontporch = video->frame_left;
791 det->hbackporch = (mds & VE_MODE_DETECT_H_PIXELS) -
792 video->frame_right;
793 det->hsync = sync & VE_SYNC_STATUS_HSYNC;
794 if (video->frame_left > video->frame_right)
795 continue;
796
797 invalid_resolution = false;
798 } while (invalid_resolution && (tries++ < INVALID_RESOLUTION_RETRIES));
799
800 if (invalid_resolution) {
801 dev_dbg(video->dev, "Invalid resolution detected\n");
802 return;
803 }
804
805 det->height = (video->frame_bottom - video->frame_top) + 1;
806 det->width = (video->frame_right - video->frame_left) + 1;
807 video->v4l2_input_status = 0;
808
809
810
811
812
813 aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
814 VE_INTERRUPT_MODE_DETECT_WD);
815 aspeed_video_update(video, VE_SEQ_CTRL, 0,
816 VE_SEQ_CTRL_AUTO_COMP | VE_SEQ_CTRL_EN_WATCHDOG);
817
818 dev_dbg(video->dev, "Got resolution: %dx%d\n", det->width,
819 det->height);
820}
821
822static void aspeed_video_set_resolution(struct aspeed_video *video)
823{
824 struct v4l2_bt_timings *act = &video->active_timings;
825 unsigned int size = act->width * act->height;
826
827
828 aspeed_video_calc_compressed_size(video, size);
829
830 if (video->active_timings.width == 1680) {
831
832
833
834
835
836
837
838
839 aspeed_video_write(video, VE_CAP_WINDOW,
840 1728 << 16 | act->height);
841 size += (1728 - 1680) * video->active_timings.height;
842 } else {
843 aspeed_video_write(video, VE_CAP_WINDOW,
844 act->width << 16 | act->height);
845 }
846 aspeed_video_write(video, VE_COMP_WINDOW,
847 act->width << 16 | act->height);
848 aspeed_video_write(video, VE_SRC_SCANLINE_OFFSET, act->width * 4);
849
850
851 if (size < DIRECT_FETCH_THRESHOLD) {
852 aspeed_video_write(video, VE_TGS_0,
853 FIELD_PREP(VE_TGS_FIRST,
854 video->frame_left - 1) |
855 FIELD_PREP(VE_TGS_LAST,
856 video->frame_right));
857 aspeed_video_write(video, VE_TGS_1,
858 FIELD_PREP(VE_TGS_FIRST, video->frame_top) |
859 FIELD_PREP(VE_TGS_LAST,
860 video->frame_bottom + 1));
861 aspeed_video_update(video, VE_CTRL, 0, VE_CTRL_INT_DE);
862 } else {
863 aspeed_video_update(video, VE_CTRL, 0, VE_CTRL_DIRECT_FETCH);
864 }
865
866 size *= 4;
867
868 if (size != video->srcs[0].size) {
869 if (video->srcs[0].size)
870 aspeed_video_free_buf(video, &video->srcs[0]);
871 if (video->srcs[1].size)
872 aspeed_video_free_buf(video, &video->srcs[1]);
873
874 if (!aspeed_video_alloc_buf(video, &video->srcs[0], size))
875 goto err_mem;
876 if (!aspeed_video_alloc_buf(video, &video->srcs[1], size))
877 goto err_mem;
878
879 aspeed_video_write(video, VE_SRC0_ADDR, video->srcs[0].dma);
880 aspeed_video_write(video, VE_SRC1_ADDR, video->srcs[1].dma);
881 }
882
883 return;
884
885err_mem:
886 dev_err(video->dev, "Failed to allocate source buffers\n");
887
888 if (video->srcs[0].size)
889 aspeed_video_free_buf(video, &video->srcs[0]);
890}
891
892static void aspeed_video_init_regs(struct aspeed_video *video)
893{
894 u32 comp_ctrl = VE_COMP_CTRL_RSVD |
895 FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |
896 FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10);
897 u32 ctrl = VE_CTRL_AUTO_OR_CURSOR;
898 u32 seq_ctrl = VE_SEQ_CTRL_JPEG_MODE;
899
900 if (video->frame_rate)
901 ctrl |= FIELD_PREP(VE_CTRL_FRC, video->frame_rate);
902
903 if (video->yuv420)
904 seq_ctrl |= VE_SEQ_CTRL_YUV420;
905
906
907 aspeed_video_write(video, VE_PROTECTION_KEY, VE_PROTECTION_KEY_UNLOCK);
908
909
910 aspeed_video_write(video, VE_INTERRUPT_CTRL, 0);
911 aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);
912
913
914 aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);
915 aspeed_video_write(video, VE_COMP_OFFSET, 0);
916
917 aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg.dma);
918
919
920 aspeed_video_write(video, VE_SEQ_CTRL, seq_ctrl);
921 aspeed_video_write(video, VE_CTRL, ctrl);
922 aspeed_video_write(video, VE_COMP_CTRL, comp_ctrl);
923
924
925 aspeed_video_write(video, VE_SCALING_FACTOR, 0x10001000);
926 aspeed_video_write(video, VE_SCALING_FILTER0, 0x00200000);
927 aspeed_video_write(video, VE_SCALING_FILTER1, 0x00200000);
928 aspeed_video_write(video, VE_SCALING_FILTER2, 0x00200000);
929 aspeed_video_write(video, VE_SCALING_FILTER3, 0x00200000);
930
931
932 aspeed_video_write(video, VE_MODE_DETECT, 0x22666500);
933}
934
935static void aspeed_video_start(struct aspeed_video *video)
936{
937 aspeed_video_on(video);
938
939 aspeed_video_init_regs(video);
940
941
942 aspeed_video_get_resolution(video);
943
944
945 video->active_timings = video->detected_timings;
946 aspeed_video_set_resolution(video);
947
948 video->pix_fmt.width = video->active_timings.width;
949 video->pix_fmt.height = video->active_timings.height;
950 video->pix_fmt.sizeimage = video->max_compressed_size;
951}
952
953static void aspeed_video_stop(struct aspeed_video *video)
954{
955 set_bit(VIDEO_STOPPED, &video->flags);
956 cancel_delayed_work_sync(&video->res_work);
957
958 aspeed_video_off(video);
959
960 if (video->srcs[0].size)
961 aspeed_video_free_buf(video, &video->srcs[0]);
962
963 if (video->srcs[1].size)
964 aspeed_video_free_buf(video, &video->srcs[1]);
965
966 video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
967 video->flags = 0;
968}
969
970static int aspeed_video_querycap(struct file *file, void *fh,
971 struct v4l2_capability *cap)
972{
973 strscpy(cap->driver, DEVICE_NAME, sizeof(cap->driver));
974 strscpy(cap->card, "Aspeed Video Engine", sizeof(cap->card));
975 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
976 DEVICE_NAME);
977
978 return 0;
979}
980
981static int aspeed_video_enum_format(struct file *file, void *fh,
982 struct v4l2_fmtdesc *f)
983{
984 if (f->index)
985 return -EINVAL;
986
987 f->pixelformat = V4L2_PIX_FMT_JPEG;
988
989 return 0;
990}
991
992static int aspeed_video_get_format(struct file *file, void *fh,
993 struct v4l2_format *f)
994{
995 struct aspeed_video *video = video_drvdata(file);
996
997 f->fmt.pix = video->pix_fmt;
998
999 return 0;
1000}
1001
1002static int aspeed_video_enum_input(struct file *file, void *fh,
1003 struct v4l2_input *inp)
1004{
1005 struct aspeed_video *video = video_drvdata(file);
1006
1007 if (inp->index)
1008 return -EINVAL;
1009
1010 strscpy(inp->name, "Host VGA capture", sizeof(inp->name));
1011 inp->type = V4L2_INPUT_TYPE_CAMERA;
1012 inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
1013 inp->status = video->v4l2_input_status;
1014
1015 return 0;
1016}
1017
1018static int aspeed_video_get_input(struct file *file, void *fh, unsigned int *i)
1019{
1020 *i = 0;
1021
1022 return 0;
1023}
1024
1025static int aspeed_video_set_input(struct file *file, void *fh, unsigned int i)
1026{
1027 if (i)
1028 return -EINVAL;
1029
1030 return 0;
1031}
1032
1033static int aspeed_video_get_parm(struct file *file, void *fh,
1034 struct v4l2_streamparm *a)
1035{
1036 struct aspeed_video *video = video_drvdata(file);
1037
1038 a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
1039 a->parm.capture.readbuffers = 3;
1040 a->parm.capture.timeperframe.numerator = 1;
1041 if (!video->frame_rate)
1042 a->parm.capture.timeperframe.denominator = MAX_FRAME_RATE;
1043 else
1044 a->parm.capture.timeperframe.denominator = video->frame_rate;
1045
1046 return 0;
1047}
1048
1049static int aspeed_video_set_parm(struct file *file, void *fh,
1050 struct v4l2_streamparm *a)
1051{
1052 unsigned int frame_rate = 0;
1053 struct aspeed_video *video = video_drvdata(file);
1054
1055 a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
1056 a->parm.capture.readbuffers = 3;
1057
1058 if (a->parm.capture.timeperframe.numerator)
1059 frame_rate = a->parm.capture.timeperframe.denominator /
1060 a->parm.capture.timeperframe.numerator;
1061
1062 if (!frame_rate || frame_rate > MAX_FRAME_RATE) {
1063 frame_rate = 0;
1064 a->parm.capture.timeperframe.denominator = MAX_FRAME_RATE;
1065 a->parm.capture.timeperframe.numerator = 1;
1066 }
1067
1068 if (video->frame_rate != frame_rate) {
1069 video->frame_rate = frame_rate;
1070 aspeed_video_update(video, VE_CTRL, VE_CTRL_FRC,
1071 FIELD_PREP(VE_CTRL_FRC, frame_rate));
1072 }
1073
1074 return 0;
1075}
1076
1077static int aspeed_video_enum_framesizes(struct file *file, void *fh,
1078 struct v4l2_frmsizeenum *fsize)
1079{
1080 struct aspeed_video *video = video_drvdata(file);
1081
1082 if (fsize->index)
1083 return -EINVAL;
1084
1085 if (fsize->pixel_format != V4L2_PIX_FMT_JPEG)
1086 return -EINVAL;
1087
1088 fsize->discrete.width = video->pix_fmt.width;
1089 fsize->discrete.height = video->pix_fmt.height;
1090 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1091
1092 return 0;
1093}
1094
1095static int aspeed_video_enum_frameintervals(struct file *file, void *fh,
1096 struct v4l2_frmivalenum *fival)
1097{
1098 struct aspeed_video *video = video_drvdata(file);
1099
1100 if (fival->index)
1101 return -EINVAL;
1102
1103 if (fival->width != video->detected_timings.width ||
1104 fival->height != video->detected_timings.height)
1105 return -EINVAL;
1106
1107 if (fival->pixel_format != V4L2_PIX_FMT_JPEG)
1108 return -EINVAL;
1109
1110 fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
1111
1112 fival->stepwise.min.denominator = MAX_FRAME_RATE;
1113 fival->stepwise.min.numerator = 1;
1114 fival->stepwise.max.denominator = 1;
1115 fival->stepwise.max.numerator = 1;
1116 fival->stepwise.step = fival->stepwise.max;
1117
1118 return 0;
1119}
1120
1121static int aspeed_video_set_dv_timings(struct file *file, void *fh,
1122 struct v4l2_dv_timings *timings)
1123{
1124 struct aspeed_video *video = video_drvdata(file);
1125
1126 if (timings->bt.width == video->active_timings.width &&
1127 timings->bt.height == video->active_timings.height)
1128 return 0;
1129
1130 if (vb2_is_busy(&video->queue))
1131 return -EBUSY;
1132
1133 video->active_timings = timings->bt;
1134
1135 aspeed_video_set_resolution(video);
1136
1137 video->pix_fmt.width = timings->bt.width;
1138 video->pix_fmt.height = timings->bt.height;
1139 video->pix_fmt.sizeimage = video->max_compressed_size;
1140
1141 timings->type = V4L2_DV_BT_656_1120;
1142
1143 return 0;
1144}
1145
1146static int aspeed_video_get_dv_timings(struct file *file, void *fh,
1147 struct v4l2_dv_timings *timings)
1148{
1149 struct aspeed_video *video = video_drvdata(file);
1150
1151 timings->type = V4L2_DV_BT_656_1120;
1152 timings->bt = video->active_timings;
1153
1154 return 0;
1155}
1156
1157static int aspeed_video_query_dv_timings(struct file *file, void *fh,
1158 struct v4l2_dv_timings *timings)
1159{
1160 int rc;
1161 struct aspeed_video *video = video_drvdata(file);
1162
1163
1164
1165
1166
1167
1168 if (file->f_flags & O_NONBLOCK) {
1169 if (test_bit(VIDEO_RES_CHANGE, &video->flags))
1170 return -EAGAIN;
1171 } else {
1172 rc = wait_event_interruptible(video->wait,
1173 !test_bit(VIDEO_RES_CHANGE,
1174 &video->flags));
1175 if (rc)
1176 return -EINTR;
1177 }
1178
1179 timings->type = V4L2_DV_BT_656_1120;
1180 timings->bt = video->detected_timings;
1181
1182 return video->v4l2_input_status ? -ENOLINK : 0;
1183}
1184
1185static int aspeed_video_enum_dv_timings(struct file *file, void *fh,
1186 struct v4l2_enum_dv_timings *timings)
1187{
1188 return v4l2_enum_dv_timings_cap(timings, &aspeed_video_timings_cap,
1189 NULL, NULL);
1190}
1191
1192static int aspeed_video_dv_timings_cap(struct file *file, void *fh,
1193 struct v4l2_dv_timings_cap *cap)
1194{
1195 *cap = aspeed_video_timings_cap;
1196
1197 return 0;
1198}
1199
1200static int aspeed_video_sub_event(struct v4l2_fh *fh,
1201 const struct v4l2_event_subscription *sub)
1202{
1203 switch (sub->type) {
1204 case V4L2_EVENT_SOURCE_CHANGE:
1205 return v4l2_src_change_event_subscribe(fh, sub);
1206 }
1207
1208 return v4l2_ctrl_subscribe_event(fh, sub);
1209}
1210
1211static const struct v4l2_ioctl_ops aspeed_video_ioctl_ops = {
1212 .vidioc_querycap = aspeed_video_querycap,
1213
1214 .vidioc_enum_fmt_vid_cap = aspeed_video_enum_format,
1215 .vidioc_g_fmt_vid_cap = aspeed_video_get_format,
1216 .vidioc_s_fmt_vid_cap = aspeed_video_get_format,
1217 .vidioc_try_fmt_vid_cap = aspeed_video_get_format,
1218
1219 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1220 .vidioc_querybuf = vb2_ioctl_querybuf,
1221 .vidioc_qbuf = vb2_ioctl_qbuf,
1222 .vidioc_expbuf = vb2_ioctl_expbuf,
1223 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1224 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1225 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1226 .vidioc_streamon = vb2_ioctl_streamon,
1227 .vidioc_streamoff = vb2_ioctl_streamoff,
1228
1229 .vidioc_enum_input = aspeed_video_enum_input,
1230 .vidioc_g_input = aspeed_video_get_input,
1231 .vidioc_s_input = aspeed_video_set_input,
1232
1233 .vidioc_g_parm = aspeed_video_get_parm,
1234 .vidioc_s_parm = aspeed_video_set_parm,
1235 .vidioc_enum_framesizes = aspeed_video_enum_framesizes,
1236 .vidioc_enum_frameintervals = aspeed_video_enum_frameintervals,
1237
1238 .vidioc_s_dv_timings = aspeed_video_set_dv_timings,
1239 .vidioc_g_dv_timings = aspeed_video_get_dv_timings,
1240 .vidioc_query_dv_timings = aspeed_video_query_dv_timings,
1241 .vidioc_enum_dv_timings = aspeed_video_enum_dv_timings,
1242 .vidioc_dv_timings_cap = aspeed_video_dv_timings_cap,
1243
1244 .vidioc_subscribe_event = aspeed_video_sub_event,
1245 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1246};
1247
1248static void aspeed_video_update_jpeg_quality(struct aspeed_video *video)
1249{
1250 u32 comp_ctrl = FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |
1251 FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10);
1252
1253 aspeed_video_update(video, VE_COMP_CTRL,
1254 VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR,
1255 comp_ctrl);
1256}
1257
1258static void aspeed_video_update_subsampling(struct aspeed_video *video)
1259{
1260 if (video->jpeg.virt)
1261 aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
1262
1263 if (video->yuv420)
1264 aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_YUV420);
1265 else
1266 aspeed_video_update(video, VE_SEQ_CTRL, VE_SEQ_CTRL_YUV420, 0);
1267}
1268
1269static int aspeed_video_set_ctrl(struct v4l2_ctrl *ctrl)
1270{
1271 struct aspeed_video *video = container_of(ctrl->handler,
1272 struct aspeed_video,
1273 ctrl_handler);
1274
1275 switch (ctrl->id) {
1276 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
1277 video->jpeg_quality = ctrl->val;
1278 aspeed_video_update_jpeg_quality(video);
1279 break;
1280 case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
1281 if (ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
1282 video->yuv420 = true;
1283 aspeed_video_update_subsampling(video);
1284 } else {
1285 video->yuv420 = false;
1286 aspeed_video_update_subsampling(video);
1287 }
1288 break;
1289 default:
1290 return -EINVAL;
1291 }
1292
1293 return 0;
1294}
1295
1296static const struct v4l2_ctrl_ops aspeed_video_ctrl_ops = {
1297 .s_ctrl = aspeed_video_set_ctrl,
1298};
1299
1300static void aspeed_video_resolution_work(struct work_struct *work)
1301{
1302 struct delayed_work *dwork = to_delayed_work(work);
1303 struct aspeed_video *video = container_of(dwork, struct aspeed_video,
1304 res_work);
1305 u32 input_status = video->v4l2_input_status;
1306
1307 aspeed_video_on(video);
1308
1309
1310 if (test_bit(VIDEO_STOPPED, &video->flags))
1311 goto done;
1312
1313 aspeed_video_init_regs(video);
1314
1315 aspeed_video_get_resolution(video);
1316
1317 if (video->detected_timings.width != video->active_timings.width ||
1318 video->detected_timings.height != video->active_timings.height ||
1319 input_status != video->v4l2_input_status) {
1320 static const struct v4l2_event ev = {
1321 .type = V4L2_EVENT_SOURCE_CHANGE,
1322 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
1323 };
1324
1325 v4l2_event_queue(&video->vdev, &ev);
1326 } else if (test_bit(VIDEO_STREAMING, &video->flags)) {
1327
1328 aspeed_video_start_frame(video);
1329 }
1330
1331done:
1332 clear_bit(VIDEO_RES_CHANGE, &video->flags);
1333 wake_up_interruptible_all(&video->wait);
1334}
1335
1336static int aspeed_video_open(struct file *file)
1337{
1338 int rc;
1339 struct aspeed_video *video = video_drvdata(file);
1340
1341 mutex_lock(&video->video_lock);
1342
1343 rc = v4l2_fh_open(file);
1344 if (rc) {
1345 mutex_unlock(&video->video_lock);
1346 return rc;
1347 }
1348
1349 if (v4l2_fh_is_singular_file(file))
1350 aspeed_video_start(video);
1351
1352 mutex_unlock(&video->video_lock);
1353
1354 return 0;
1355}
1356
1357static int aspeed_video_release(struct file *file)
1358{
1359 int rc;
1360 struct aspeed_video *video = video_drvdata(file);
1361
1362 mutex_lock(&video->video_lock);
1363
1364 if (v4l2_fh_is_singular_file(file))
1365 aspeed_video_stop(video);
1366
1367 rc = _vb2_fop_release(file, NULL);
1368
1369 mutex_unlock(&video->video_lock);
1370
1371 return rc;
1372}
1373
1374static const struct v4l2_file_operations aspeed_video_v4l2_fops = {
1375 .owner = THIS_MODULE,
1376 .read = vb2_fop_read,
1377 .poll = vb2_fop_poll,
1378 .unlocked_ioctl = video_ioctl2,
1379 .mmap = vb2_fop_mmap,
1380 .open = aspeed_video_open,
1381 .release = aspeed_video_release,
1382};
1383
1384static int aspeed_video_queue_setup(struct vb2_queue *q,
1385 unsigned int *num_buffers,
1386 unsigned int *num_planes,
1387 unsigned int sizes[],
1388 struct device *alloc_devs[])
1389{
1390 struct aspeed_video *video = vb2_get_drv_priv(q);
1391
1392 if (*num_planes) {
1393 if (sizes[0] < video->max_compressed_size)
1394 return -EINVAL;
1395
1396 return 0;
1397 }
1398
1399 *num_planes = 1;
1400 sizes[0] = video->max_compressed_size;
1401
1402 return 0;
1403}
1404
1405static int aspeed_video_buf_prepare(struct vb2_buffer *vb)
1406{
1407 struct aspeed_video *video = vb2_get_drv_priv(vb->vb2_queue);
1408
1409 if (vb2_plane_size(vb, 0) < video->max_compressed_size)
1410 return -EINVAL;
1411
1412 return 0;
1413}
1414
1415static int aspeed_video_start_streaming(struct vb2_queue *q,
1416 unsigned int count)
1417{
1418 int rc;
1419 struct aspeed_video *video = vb2_get_drv_priv(q);
1420
1421 video->sequence = 0;
1422
1423 rc = aspeed_video_start_frame(video);
1424 if (rc) {
1425 aspeed_video_bufs_done(video, VB2_BUF_STATE_QUEUED);
1426 return rc;
1427 }
1428
1429 set_bit(VIDEO_STREAMING, &video->flags);
1430 return 0;
1431}
1432
1433static void aspeed_video_stop_streaming(struct vb2_queue *q)
1434{
1435 int rc;
1436 struct aspeed_video *video = vb2_get_drv_priv(q);
1437
1438 clear_bit(VIDEO_STREAMING, &video->flags);
1439
1440 rc = wait_event_timeout(video->wait,
1441 !test_bit(VIDEO_FRAME_INPRG, &video->flags),
1442 STOP_TIMEOUT);
1443 if (!rc) {
1444 dev_dbg(video->dev, "Timed out when stopping streaming\n");
1445
1446
1447
1448
1449
1450 aspeed_video_off(video);
1451 aspeed_video_on(video);
1452
1453 aspeed_video_init_regs(video);
1454
1455 aspeed_video_get_resolution(video);
1456 }
1457
1458 aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);
1459}
1460
1461static void aspeed_video_buf_queue(struct vb2_buffer *vb)
1462{
1463 bool empty;
1464 struct aspeed_video *video = vb2_get_drv_priv(vb->vb2_queue);
1465 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1466 struct aspeed_video_buffer *avb = to_aspeed_video_buffer(vbuf);
1467 unsigned long flags;
1468
1469 spin_lock_irqsave(&video->lock, flags);
1470 empty = list_empty(&video->buffers);
1471 list_add_tail(&avb->link, &video->buffers);
1472 spin_unlock_irqrestore(&video->lock, flags);
1473
1474 if (test_bit(VIDEO_STREAMING, &video->flags) &&
1475 !test_bit(VIDEO_FRAME_INPRG, &video->flags) && empty)
1476 aspeed_video_start_frame(video);
1477}
1478
1479static const struct vb2_ops aspeed_video_vb2_ops = {
1480 .queue_setup = aspeed_video_queue_setup,
1481 .wait_prepare = vb2_ops_wait_prepare,
1482 .wait_finish = vb2_ops_wait_finish,
1483 .buf_prepare = aspeed_video_buf_prepare,
1484 .start_streaming = aspeed_video_start_streaming,
1485 .stop_streaming = aspeed_video_stop_streaming,
1486 .buf_queue = aspeed_video_buf_queue,
1487};
1488
1489static int aspeed_video_setup_video(struct aspeed_video *video)
1490{
1491 const u64 mask = ~(BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_444) |
1492 BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_420));
1493 struct v4l2_device *v4l2_dev = &video->v4l2_dev;
1494 struct vb2_queue *vbq = &video->queue;
1495 struct video_device *vdev = &video->vdev;
1496 int rc;
1497
1498 video->pix_fmt.pixelformat = V4L2_PIX_FMT_JPEG;
1499 video->pix_fmt.field = V4L2_FIELD_NONE;
1500 video->pix_fmt.colorspace = V4L2_COLORSPACE_SRGB;
1501 video->pix_fmt.quantization = V4L2_QUANTIZATION_FULL_RANGE;
1502 video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
1503
1504 rc = v4l2_device_register(video->dev, v4l2_dev);
1505 if (rc) {
1506 dev_err(video->dev, "Failed to register v4l2 device\n");
1507 return rc;
1508 }
1509
1510 v4l2_ctrl_handler_init(&video->ctrl_handler, 2);
1511 v4l2_ctrl_new_std(&video->ctrl_handler, &aspeed_video_ctrl_ops,
1512 V4L2_CID_JPEG_COMPRESSION_QUALITY, 0,
1513 ASPEED_VIDEO_JPEG_NUM_QUALITIES - 1, 1, 0);
1514 v4l2_ctrl_new_std_menu(&video->ctrl_handler, &aspeed_video_ctrl_ops,
1515 V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
1516 V4L2_JPEG_CHROMA_SUBSAMPLING_420, mask,
1517 V4L2_JPEG_CHROMA_SUBSAMPLING_444);
1518
1519 if (video->ctrl_handler.error) {
1520 v4l2_ctrl_handler_free(&video->ctrl_handler);
1521 v4l2_device_unregister(v4l2_dev);
1522
1523 dev_err(video->dev, "Failed to init controls: %d\n",
1524 video->ctrl_handler.error);
1525 return rc;
1526 }
1527
1528 v4l2_dev->ctrl_handler = &video->ctrl_handler;
1529
1530 vbq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1531 vbq->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
1532 vbq->dev = v4l2_dev->dev;
1533 vbq->lock = &video->video_lock;
1534 vbq->ops = &aspeed_video_vb2_ops;
1535 vbq->mem_ops = &vb2_dma_contig_memops;
1536 vbq->drv_priv = video;
1537 vbq->buf_struct_size = sizeof(struct aspeed_video_buffer);
1538 vbq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1539 vbq->min_buffers_needed = 3;
1540
1541 rc = vb2_queue_init(vbq);
1542 if (rc) {
1543 v4l2_ctrl_handler_free(&video->ctrl_handler);
1544 v4l2_device_unregister(v4l2_dev);
1545
1546 dev_err(video->dev, "Failed to init vb2 queue\n");
1547 return rc;
1548 }
1549
1550 vdev->queue = vbq;
1551 vdev->fops = &aspeed_video_v4l2_fops;
1552 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
1553 V4L2_CAP_STREAMING;
1554 vdev->v4l2_dev = v4l2_dev;
1555 strscpy(vdev->name, DEVICE_NAME, sizeof(vdev->name));
1556 vdev->vfl_type = VFL_TYPE_GRABBER;
1557 vdev->vfl_dir = VFL_DIR_RX;
1558 vdev->release = video_device_release_empty;
1559 vdev->ioctl_ops = &aspeed_video_ioctl_ops;
1560 vdev->lock = &video->video_lock;
1561
1562 video_set_drvdata(vdev, video);
1563 rc = video_register_device(vdev, VFL_TYPE_GRABBER, 0);
1564 if (rc) {
1565 vb2_queue_release(vbq);
1566 v4l2_ctrl_handler_free(&video->ctrl_handler);
1567 v4l2_device_unregister(v4l2_dev);
1568
1569 dev_err(video->dev, "Failed to register video device\n");
1570 return rc;
1571 }
1572
1573 return 0;
1574}
1575
1576static int aspeed_video_init(struct aspeed_video *video)
1577{
1578 int irq;
1579 int rc;
1580 struct device *dev = video->dev;
1581
1582 irq = irq_of_parse_and_map(dev->of_node, 0);
1583 if (!irq) {
1584 dev_err(dev, "Unable to find IRQ\n");
1585 return -ENODEV;
1586 }
1587
1588 rc = devm_request_threaded_irq(dev, irq, NULL, aspeed_video_irq,
1589 IRQF_ONESHOT, DEVICE_NAME, video);
1590 if (rc < 0) {
1591 dev_err(dev, "Unable to request IRQ %d\n", irq);
1592 return rc;
1593 }
1594
1595 video->eclk = devm_clk_get(dev, "eclk");
1596 if (IS_ERR(video->eclk)) {
1597 dev_err(dev, "Unable to get ECLK\n");
1598 return PTR_ERR(video->eclk);
1599 }
1600
1601 rc = clk_prepare(video->eclk);
1602 if (rc)
1603 return rc;
1604
1605 video->vclk = devm_clk_get(dev, "vclk");
1606 if (IS_ERR(video->vclk)) {
1607 dev_err(dev, "Unable to get VCLK\n");
1608 rc = PTR_ERR(video->vclk);
1609 goto err_unprepare_eclk;
1610 }
1611
1612 rc = clk_prepare(video->vclk);
1613 if (rc)
1614 goto err_unprepare_eclk;
1615
1616 of_reserved_mem_device_init(dev);
1617
1618 rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
1619 if (rc) {
1620 dev_err(dev, "Failed to set DMA mask\n");
1621 goto err_release_reserved_mem;
1622 }
1623
1624 if (!aspeed_video_alloc_buf(video, &video->jpeg,
1625 VE_JPEG_HEADER_SIZE)) {
1626 dev_err(dev, "Failed to allocate DMA for JPEG header\n");
1627 goto err_release_reserved_mem;
1628 }
1629
1630 aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
1631
1632 return 0;
1633
1634err_release_reserved_mem:
1635 of_reserved_mem_device_release(dev);
1636 clk_unprepare(video->vclk);
1637err_unprepare_eclk:
1638 clk_unprepare(video->eclk);
1639
1640 return rc;
1641}
1642
1643static int aspeed_video_probe(struct platform_device *pdev)
1644{
1645 int rc;
1646 struct resource *res;
1647 struct aspeed_video *video = kzalloc(sizeof(*video), GFP_KERNEL);
1648
1649 if (!video)
1650 return -ENOMEM;
1651
1652 video->frame_rate = 30;
1653 video->dev = &pdev->dev;
1654 spin_lock_init(&video->lock);
1655 mutex_init(&video->video_lock);
1656 init_waitqueue_head(&video->wait);
1657 INIT_DELAYED_WORK(&video->res_work, aspeed_video_resolution_work);
1658 INIT_LIST_HEAD(&video->buffers);
1659
1660 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1661
1662 video->base = devm_ioremap_resource(video->dev, res);
1663
1664 if (IS_ERR(video->base))
1665 return PTR_ERR(video->base);
1666
1667 rc = aspeed_video_init(video);
1668 if (rc)
1669 return rc;
1670
1671 rc = aspeed_video_setup_video(video);
1672 if (rc)
1673 return rc;
1674
1675 return 0;
1676}
1677
1678static int aspeed_video_remove(struct platform_device *pdev)
1679{
1680 struct device *dev = &pdev->dev;
1681 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1682 struct aspeed_video *video = to_aspeed_video(v4l2_dev);
1683
1684 aspeed_video_off(video);
1685
1686 clk_unprepare(video->vclk);
1687 clk_unprepare(video->eclk);
1688
1689 video_unregister_device(&video->vdev);
1690
1691 vb2_queue_release(&video->queue);
1692
1693 v4l2_ctrl_handler_free(&video->ctrl_handler);
1694
1695 v4l2_device_unregister(v4l2_dev);
1696
1697 dma_free_coherent(video->dev, VE_JPEG_HEADER_SIZE, video->jpeg.virt,
1698 video->jpeg.dma);
1699
1700 of_reserved_mem_device_release(dev);
1701
1702 return 0;
1703}
1704
1705static const struct of_device_id aspeed_video_of_match[] = {
1706 { .compatible = "aspeed,ast2400-video-engine" },
1707 { .compatible = "aspeed,ast2500-video-engine" },
1708 {}
1709};
1710MODULE_DEVICE_TABLE(of, aspeed_video_of_match);
1711
1712static struct platform_driver aspeed_video_driver = {
1713 .driver = {
1714 .name = DEVICE_NAME,
1715 .of_match_table = aspeed_video_of_match,
1716 },
1717 .probe = aspeed_video_probe,
1718 .remove = aspeed_video_remove,
1719};
1720
1721module_platform_driver(aspeed_video_driver);
1722
1723MODULE_DESCRIPTION("ASPEED Video Engine Driver");
1724MODULE_AUTHOR("Eddie James");
1725MODULE_LICENSE("GPL v2");
1726