brintos

brintos / linux-shallow public Read only

0
0
Text · 66.3 KiB · fc6050e Raw
2240 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2// Copyright 2020 IBM Corp.3// Copyright (c) 2019-2020 Intel Corporation4 5#include <linux/atomic.h>6#include <linux/bitfield.h>7#include <linux/clk.h>8#include <linux/delay.h>9#include <linux/device.h>10#include <linux/dma-mapping.h>11#include <linux/interrupt.h>12#include <linux/jiffies.h>13#include <linux/module.h>14#include <linux/mutex.h>15#include <linux/of.h>16#include <linux/of_irq.h>17#include <linux/of_reserved_mem.h>18#include <linux/platform_device.h>19#include <linux/sched.h>20#include <linux/spinlock.h>21#include <linux/string.h>22#include <linux/v4l2-controls.h>23#include <linux/videodev2.h>24#include <linux/wait.h>25#include <linux/workqueue.h>26#include <linux/debugfs.h>27#include <linux/ktime.h>28#include <media/v4l2-ctrls.h>29#include <media/v4l2-dev.h>30#include <media/v4l2-device.h>31#include <media/v4l2-dv-timings.h>32#include <media/v4l2-event.h>33#include <media/v4l2-ioctl.h>34#include <media/videobuf2-dma-contig.h>35#include <uapi/linux/aspeed-video.h>36 37#define ASPEED_VIDEO_V4L2_MIN_BUF_REQ 338 39#define DEVICE_NAME			"aspeed-video"40 41#define ASPEED_VIDEO_JPEG_NUM_QUALITIES	1242#define ASPEED_VIDEO_JPEG_HEADER_SIZE	1043#define ASPEED_VIDEO_JPEG_QUANT_SIZE	11644#define ASPEED_VIDEO_JPEG_DCT_SIZE	3445 46#define MAX_FRAME_RATE			6047#define MAX_HEIGHT			120048#define MAX_WIDTH			192049#define MIN_HEIGHT			48050#define MIN_WIDTH			64051 52#define NUM_POLARITY_CHECKS		1053#define INVALID_RESOLUTION_RETRIES	254#define INVALID_RESOLUTION_DELAY	msecs_to_jiffies(250)55#define RESOLUTION_CHANGE_DELAY		msecs_to_jiffies(500)56#define MODE_DETECT_TIMEOUT		msecs_to_jiffies(500)57#define STOP_TIMEOUT			msecs_to_jiffies(1000)58#define DIRECT_FETCH_THRESHOLD		0x0c0000 /* 1024 * 768 */59 60#define VE_MAX_SRC_BUFFER_SIZE		0x8ca000 /* 1920 * 1200, 32bpp */61#define VE_JPEG_HEADER_SIZE		0x006000 /* 512 * 12 * 4 */62#define VE_BCD_BUFF_SIZE		0x9000 /* (1920/8) * (1200/8) */63 64#define VE_PROTECTION_KEY		0x00065#define  VE_PROTECTION_KEY_UNLOCK	0x1a038aa866 67#define VE_SEQ_CTRL			0x00468#define  VE_SEQ_CTRL_TRIG_MODE_DET	BIT(0)69#define  VE_SEQ_CTRL_TRIG_CAPTURE	BIT(1)70#define  VE_SEQ_CTRL_FORCE_IDLE		BIT(2)71#define  VE_SEQ_CTRL_MULT_FRAME		BIT(3)72#define  VE_SEQ_CTRL_TRIG_COMP		BIT(4)73#define  VE_SEQ_CTRL_AUTO_COMP		BIT(5)74#define  VE_SEQ_CTRL_EN_WATCHDOG	BIT(7)75#define  VE_SEQ_CTRL_YUV420		BIT(10)76#define  VE_SEQ_CTRL_COMP_FMT		GENMASK(11, 10)77#define  VE_SEQ_CTRL_HALT		BIT(12)78#define  VE_SEQ_CTRL_EN_WATCHDOG_COMP	BIT(14)79#define  VE_SEQ_CTRL_TRIG_JPG		BIT(15)80#define  VE_SEQ_CTRL_CAP_BUSY		BIT(16)81#define  VE_SEQ_CTRL_COMP_BUSY		BIT(18)82 83#define AST2500_VE_SEQ_CTRL_JPEG_MODE	BIT(13)84#define AST2400_VE_SEQ_CTRL_JPEG_MODE	BIT(8)85 86#define VE_CTRL				0x00887#define  VE_CTRL_HSYNC_POL		BIT(0)88#define  VE_CTRL_VSYNC_POL		BIT(1)89#define  VE_CTRL_SOURCE			BIT(2)90#define  VE_CTRL_INT_DE			BIT(4)91#define  VE_CTRL_DIRECT_FETCH		BIT(5)92#define  VE_CTRL_CAPTURE_FMT		GENMASK(7, 6)93#define  VE_CTRL_AUTO_OR_CURSOR		BIT(8)94#define  VE_CTRL_CLK_INVERSE		BIT(11)95#define  VE_CTRL_CLK_DELAY		GENMASK(11, 9)96#define  VE_CTRL_INTERLACE		BIT(14)97#define  VE_CTRL_HSYNC_POL_CTRL		BIT(15)98#define  VE_CTRL_FRC			GENMASK(23, 16)99 100#define VE_TGS_0			0x00c101#define VE_TGS_1			0x010102#define  VE_TGS_FIRST			GENMASK(28, 16)103#define  VE_TGS_LAST			GENMASK(12, 0)104 105#define VE_SCALING_FACTOR		0x014106#define VE_SCALING_FILTER0		0x018107#define VE_SCALING_FILTER1		0x01c108#define VE_SCALING_FILTER2		0x020109#define VE_SCALING_FILTER3		0x024110 111#define VE_BCD_CTRL			0x02C112#define  VE_BCD_CTRL_EN_BCD		BIT(0)113#define  VE_BCD_CTRL_EN_ABCD		BIT(1)114#define  VE_BCD_CTRL_EN_CB		BIT(2)115#define  VE_BCD_CTRL_THR		GENMASK(23, 16)116#define  VE_BCD_CTRL_ABCD_THR		GENMASK(31, 24)117 118#define VE_CAP_WINDOW			0x030119#define VE_COMP_WINDOW			0x034120#define VE_COMP_PROC_OFFSET		0x038121#define VE_COMP_OFFSET			0x03c122#define VE_JPEG_ADDR			0x040123#define VE_SRC0_ADDR			0x044124#define VE_SRC_SCANLINE_OFFSET		0x048125#define VE_SRC1_ADDR			0x04c126#define VE_BCD_ADDR			0x050127#define VE_COMP_ADDR			0x054128 129#define VE_STREAM_BUF_SIZE		0x058130#define  VE_STREAM_BUF_SIZE_N_PACKETS	GENMASK(5, 3)131#define  VE_STREAM_BUF_SIZE_P_SIZE	GENMASK(2, 0)132 133#define VE_COMP_CTRL			0x060134#define  VE_COMP_CTRL_VQ_DCT_ONLY	BIT(0)135#define  VE_COMP_CTRL_VQ_4COLOR		BIT(1)136#define  VE_COMP_CTRL_QUANTIZE		BIT(2)137#define  VE_COMP_CTRL_EN_BQ		BIT(4)138#define  VE_COMP_CTRL_EN_CRYPTO		BIT(5)139#define  VE_COMP_CTRL_DCT_CHR		GENMASK(10, 6)140#define  VE_COMP_CTRL_DCT_LUM		GENMASK(15, 11)141#define  VE_COMP_CTRL_EN_HQ		BIT(16)142#define  VE_COMP_CTRL_RSVD		BIT(19)143#define  VE_COMP_CTRL_ENCODE		GENMASK(21, 20)144#define  VE_COMP_CTRL_HQ_DCT_CHR	GENMASK(26, 22)145#define  VE_COMP_CTRL_HQ_DCT_LUM	GENMASK(31, 27)146 147#define VE_CB_ADDR			0x06C148 149#define AST2400_VE_COMP_SIZE_READ_BACK	0x078150#define AST2600_VE_COMP_SIZE_READ_BACK	0x084151 152#define VE_SRC_LR_EDGE_DET		0x090153#define  VE_SRC_LR_EDGE_DET_LEFT	GENMASK(11, 0)154#define  VE_SRC_LR_EDGE_DET_NO_V	BIT(12)155#define  VE_SRC_LR_EDGE_DET_NO_H	BIT(13)156#define  VE_SRC_LR_EDGE_DET_NO_DISP	BIT(14)157#define  VE_SRC_LR_EDGE_DET_NO_CLK	BIT(15)158#define  VE_SRC_LR_EDGE_DET_RT		GENMASK(27, 16)159#define  VE_SRC_LR_EDGE_DET_INTERLACE	BIT(31)160 161#define VE_SRC_TB_EDGE_DET		0x094162#define  VE_SRC_TB_EDGE_DET_TOP		GENMASK(12, 0)163#define  VE_SRC_TB_EDGE_DET_BOT		GENMASK(28, 16)164 165#define VE_MODE_DETECT_STATUS		0x098166#define  VE_MODE_DETECT_H_PERIOD	GENMASK(11, 0)167#define  VE_MODE_DETECT_EXTSRC_ADC	BIT(12)168#define  VE_MODE_DETECT_H_STABLE	BIT(13)169#define  VE_MODE_DETECT_V_STABLE	BIT(14)170#define  VE_MODE_DETECT_V_LINES		GENMASK(27, 16)171#define  VE_MODE_DETECT_STATUS_VSYNC	BIT(28)172#define  VE_MODE_DETECT_STATUS_HSYNC	BIT(29)173#define  VE_MODE_DETECT_VSYNC_RDY	BIT(30)174#define  VE_MODE_DETECT_HSYNC_RDY	BIT(31)175 176#define VE_SYNC_STATUS			0x09c177#define  VE_SYNC_STATUS_HSYNC		GENMASK(11, 0)178#define  VE_SYNC_STATUS_VSYNC		GENMASK(27, 16)179 180#define VE_H_TOTAL_PIXELS		0x0A0181 182#define VE_INTERRUPT_CTRL		0x304183#define VE_INTERRUPT_STATUS		0x308184#define  VE_INTERRUPT_MODE_DETECT_WD	BIT(0)185#define  VE_INTERRUPT_CAPTURE_COMPLETE	BIT(1)186#define  VE_INTERRUPT_COMP_READY	BIT(2)187#define  VE_INTERRUPT_COMP_COMPLETE	BIT(3)188#define  VE_INTERRUPT_MODE_DETECT	BIT(4)189#define  VE_INTERRUPT_FRAME_COMPLETE	BIT(5)190#define  VE_INTERRUPT_DECODE_ERR	BIT(6)191#define  VE_INTERRUPT_HALT_READY	BIT(8)192#define  VE_INTERRUPT_HANG_WD		BIT(9)193#define  VE_INTERRUPT_STREAM_DESC	BIT(10)194#define  VE_INTERRUPT_VSYNC_DESC	BIT(11)195 196#define VE_MODE_DETECT			0x30c197#define  VE_MODE_DT_HOR_TOLER		GENMASK(31, 28)198#define  VE_MODE_DT_VER_TOLER		GENMASK(27, 24)199#define  VE_MODE_DT_HOR_STABLE		GENMASK(23, 20)200#define  VE_MODE_DT_VER_STABLE		GENMASK(19, 16)201#define  VE_MODE_DT_EDG_THROD		GENMASK(15, 8)202 203#define VE_MEM_RESTRICT_START		0x310204#define VE_MEM_RESTRICT_END		0x314205 206/*207 * VIDEO_MODE_DETECT_DONE:	a flag raised if signal lock208 * VIDEO_RES_CHANGE:		a flag raised if res_change work on-going209 * VIDEO_RES_DETECT:		a flag raised if res. detection on-going210 * VIDEO_STREAMING:		a flag raised if user requires stream-on211 * VIDEO_FRAME_INPRG:		a flag raised if hw working on a frame212 * VIDEO_STOPPED:		a flag raised if device release213 * VIDEO_CLOCKS_ON:		a flag raised if clk is on214 */215enum {216	VIDEO_MODE_DETECT_DONE,217	VIDEO_RES_CHANGE,218	VIDEO_RES_DETECT,219	VIDEO_STREAMING,220	VIDEO_FRAME_INPRG,221	VIDEO_STOPPED,222	VIDEO_CLOCKS_ON,223};224 225enum aspeed_video_format {226	VIDEO_FMT_STANDARD = 0,227	VIDEO_FMT_ASPEED,228	VIDEO_FMT_MAX = VIDEO_FMT_ASPEED229};230 231// for VE_CTRL_CAPTURE_FMT232enum aspeed_video_capture_format {233	VIDEO_CAP_FMT_YUV_STUDIO_SWING = 0,234	VIDEO_CAP_FMT_YUV_FULL_SWING,235	VIDEO_CAP_FMT_RGB,236	VIDEO_CAP_FMT_GRAY,237	VIDEO_CAP_FMT_MAX238};239 240struct aspeed_video_addr {241	unsigned int size;242	dma_addr_t dma;243	void *virt;244};245 246struct aspeed_video_buffer {247	struct vb2_v4l2_buffer vb;248	struct list_head link;249};250 251struct aspeed_video_perf {252	ktime_t last_sample;253	u32 totaltime;254	u32 duration;255	u32 duration_min;256	u32 duration_max;257};258 259#define to_aspeed_video_buffer(x) \260	container_of((x), struct aspeed_video_buffer, vb)261 262/*263 * struct aspeed_video - driver data264 *265 * res_work:		holds the delayed_work for res-detection if unlock266 * buffers:		holds the list of buffer queued from user267 * flags:		holds the state of video268 * sequence:		holds the last number of frame completed269 * max_compressed_size:	holds max compressed stream's size270 * srcs:		holds the buffer information for srcs271 * jpeg:		holds the buffer information for jpeg header272 * bcd:			holds the buffer information for bcd work273 * yuv420:		a flag raised if JPEG subsampling is 420274 * format:		holds the video format275 * hq_mode:		a flag raised if HQ is enabled. Only for VIDEO_FMT_ASPEED276 * frame_rate:		holds the frame_rate277 * jpeg_quality:	holds jpeq's quality (0~11)278 * jpeg_hq_quality:	holds hq's quality (1~12) only if hq_mode enabled279 * frame_bottom:	end position of video data in vertical direction280 * frame_left:		start position of video data in horizontal direction281 * frame_right:		end position of video data in horizontal direction282 * frame_top:		start position of video data in vertical direction283 * perf:		holds the statistics primary for debugfs284 */285struct aspeed_video {286	void __iomem *base;287	struct clk *eclk;288	struct clk *vclk;289 290	struct device *dev;291	struct v4l2_ctrl_handler ctrl_handler;292	struct v4l2_device v4l2_dev;293	struct v4l2_pix_format pix_fmt;294	struct v4l2_bt_timings active_timings;295	struct v4l2_bt_timings detected_timings;296	u32 v4l2_input_status;297	struct vb2_queue queue;298	struct video_device vdev;299	struct mutex video_lock;	/* v4l2 and videobuf2 lock */300 301	u32 jpeg_mode;302	u32 comp_size_read;303 304	wait_queue_head_t wait;305	spinlock_t lock;		/* buffer list lock */306	struct delayed_work res_work;307	struct list_head buffers;308	unsigned long flags;309	unsigned int sequence;310 311	unsigned int max_compressed_size;312	struct aspeed_video_addr srcs[2];313	struct aspeed_video_addr jpeg;314	struct aspeed_video_addr bcd;315 316	bool yuv420;317	enum aspeed_video_format format;318	bool hq_mode;319	unsigned int frame_rate;320	unsigned int jpeg_quality;321	unsigned int jpeg_hq_quality;322 323	unsigned int frame_bottom;324	unsigned int frame_left;325	unsigned int frame_right;326	unsigned int frame_top;327 328	struct aspeed_video_perf perf;329};330 331#define to_aspeed_video(x) container_of((x), struct aspeed_video, v4l2_dev)332 333struct aspeed_video_config {334	u32 jpeg_mode;335	u32 comp_size_read;336};337 338static const struct aspeed_video_config ast2400_config = {339	.jpeg_mode = AST2400_VE_SEQ_CTRL_JPEG_MODE,340	.comp_size_read = AST2400_VE_COMP_SIZE_READ_BACK,341};342 343static const struct aspeed_video_config ast2500_config = {344	.jpeg_mode = AST2500_VE_SEQ_CTRL_JPEG_MODE,345	.comp_size_read = AST2400_VE_COMP_SIZE_READ_BACK,346};347 348static const struct aspeed_video_config ast2600_config = {349	.jpeg_mode = AST2500_VE_SEQ_CTRL_JPEG_MODE,350	.comp_size_read = AST2600_VE_COMP_SIZE_READ_BACK,351};352 353static const u32 aspeed_video_jpeg_header[ASPEED_VIDEO_JPEG_HEADER_SIZE] = {354	0xe0ffd8ff, 0x464a1000, 0x01004649, 0x60000101, 0x00006000, 0x0f00feff,355	0x00002d05, 0x00000000, 0x00000000, 0x00dbff00356};357 358static const u32 aspeed_video_jpeg_quant[ASPEED_VIDEO_JPEG_QUANT_SIZE] = {359	0x081100c0, 0x00000000, 0x00110103, 0x03011102, 0xc4ff0111, 0x00001f00,360	0x01010501, 0x01010101, 0x00000000, 0x00000000, 0x04030201, 0x08070605,361	0xff0b0a09, 0x10b500c4, 0x03010200, 0x03040203, 0x04040505, 0x7d010000,362	0x00030201, 0x12051104, 0x06413121, 0x07615113, 0x32147122, 0x08a19181,363	0xc1b14223, 0xf0d15215, 0x72623324, 0x160a0982, 0x1a191817, 0x28272625,364	0x35342a29, 0x39383736, 0x4544433a, 0x49484746, 0x5554534a, 0x59585756,365	0x6564635a, 0x69686766, 0x7574736a, 0x79787776, 0x8584837a, 0x89888786,366	0x9493928a, 0x98979695, 0xa3a29a99, 0xa7a6a5a4, 0xb2aaa9a8, 0xb6b5b4b3,367	0xbab9b8b7, 0xc5c4c3c2, 0xc9c8c7c6, 0xd4d3d2ca, 0xd8d7d6d5, 0xe2e1dad9,368	0xe6e5e4e3, 0xeae9e8e7, 0xf4f3f2f1, 0xf8f7f6f5, 0xc4fffaf9, 0x00011f00,369	0x01010103, 0x01010101, 0x00000101, 0x00000000, 0x04030201, 0x08070605,370	0xff0b0a09, 0x11b500c4, 0x02010200, 0x04030404, 0x04040507, 0x77020100,371	0x03020100, 0x21050411, 0x41120631, 0x71610751, 0x81322213, 0x91421408,372	0x09c1b1a1, 0xf0523323, 0xd1726215, 0x3424160a, 0x17f125e1, 0x261a1918,373	0x2a292827, 0x38373635, 0x44433a39, 0x48474645, 0x54534a49, 0x58575655,374	0x64635a59, 0x68676665, 0x74736a69, 0x78777675, 0x83827a79, 0x87868584,375	0x928a8988, 0x96959493, 0x9a999897, 0xa5a4a3a2, 0xa9a8a7a6, 0xb4b3b2aa,376	0xb8b7b6b5, 0xc3c2bab9, 0xc7c6c5c4, 0xd2cac9c8, 0xd6d5d4d3, 0xdad9d8d7,377	0xe5e4e3e2, 0xe9e8e7e6, 0xf4f3f2ea, 0xf8f7f6f5, 0xdafffaf9, 0x01030c00,378	0x03110200, 0x003f0011379};380 381static const u32 aspeed_video_jpeg_dct[ASPEED_VIDEO_JPEG_NUM_QUALITIES]382				      [ASPEED_VIDEO_JPEG_DCT_SIZE] = {383	{ 0x0d140043, 0x0c0f110f, 0x11101114, 0x17141516, 0x1e20321e,384	  0x3d1e1b1b, 0x32242e2b, 0x4b4c3f48, 0x44463f47, 0x61735a50,385	  0x566c5550, 0x88644644, 0x7a766c65, 0x4d808280, 0x8c978d60,386	  0x7e73967d, 0xdbff7b80, 0x1f014300, 0x272d2121, 0x3030582d,387	  0x697bb958, 0xb8b9b97b, 0xb9b8a6a6, 0xb9b9b9b9, 0xb9b9b9b9,388	  0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9,389	  0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xffb9b9b9 },390	{ 0x0c110043, 0x0a0d0f0d, 0x0f0e0f11, 0x14111213, 0x1a1c2b1a,391	  0x351a1818, 0x2b1f2826, 0x4142373f, 0x3c3d373e, 0x55644e46,392	  0x4b5f4a46, 0x77573d3c, 0x6b675f58, 0x43707170, 0x7a847b54,393	  0x6e64836d, 0xdbff6c70, 0x1b014300, 0x22271d1d, 0x2a2a4c27,394	  0x5b6ba04c, 0xa0a0a06b, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0,395	  0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0,396	  0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xffa0a0a0 },397	{ 0x090e0043, 0x090a0c0a, 0x0c0b0c0e, 0x110e0f10, 0x15172415,398	  0x2c151313, 0x241a211f, 0x36372e34, 0x31322e33, 0x4653413a,399	  0x3e4e3d3a, 0x62483231, 0x58564e49, 0x385d5e5d, 0x656d6645,400	  0x5b536c5a, 0xdbff595d, 0x16014300, 0x1c201818, 0x22223f20,401	  0x4b58853f, 0x85858558, 0x85858585, 0x85858585, 0x85858585,402	  0x85858585, 0x85858585, 0x85858585, 0x85858585, 0x85858585,403	  0x85858585, 0x85858585, 0x85858585, 0xff858585 },404	{ 0x070b0043, 0x07080a08, 0x0a090a0b, 0x0d0b0c0c, 0x11121c11,405	  0x23110f0f, 0x1c141a19, 0x2b2b2429, 0x27282428, 0x3842332e,406	  0x313e302e, 0x4e392827, 0x46443e3a, 0x2c4a4a4a, 0x50565137,407	  0x48425647, 0xdbff474a, 0x12014300, 0x161a1313, 0x1c1c331a,408	  0x3d486c33, 0x6c6c6c48, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c,409	  0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c,410	  0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0xff6c6c6c },411	{ 0x06090043, 0x05060706, 0x07070709, 0x0a09090a, 0x0d0e160d,412	  0x1b0d0c0c, 0x16101413, 0x21221c20, 0x1e1f1c20, 0x2b332824,413	  0x26302624, 0x3d2d1f1e, 0x3735302d, 0x22393a39, 0x3f443f2b,414	  0x38334338, 0xdbff3739, 0x0d014300, 0x11130e0e, 0x15152613,415	  0x2d355026, 0x50505035, 0x50505050, 0x50505050, 0x50505050,416	  0x50505050, 0x50505050, 0x50505050, 0x50505050, 0x50505050,417	  0x50505050, 0x50505050, 0x50505050, 0xff505050 },418	{ 0x04060043, 0x03040504, 0x05040506, 0x07060606, 0x09090f09,419	  0x12090808, 0x0f0a0d0d, 0x16161315, 0x14151315, 0x1d221b18,420	  0x19201918, 0x281e1514, 0x2423201e, 0x17262726, 0x2a2d2a1c,421	  0x25222d25, 0xdbff2526, 0x09014300, 0x0b0d0a0a, 0x0e0e1a0d,422	  0x1f25371a, 0x37373725, 0x37373737, 0x37373737, 0x37373737,423	  0x37373737, 0x37373737, 0x37373737, 0x37373737, 0x37373737,424	  0x37373737, 0x37373737, 0x37373737, 0xff373737 },425	{ 0x02030043, 0x01020202, 0x02020203, 0x03030303, 0x04040704,426	  0x09040404, 0x07050606, 0x0b0b090a, 0x0a0a090a, 0x0e110d0c,427	  0x0c100c0c, 0x140f0a0a, 0x1211100f, 0x0b131313, 0x1516150e,428	  0x12111612, 0xdbff1213, 0x04014300, 0x05060505, 0x07070d06,429	  0x0f121b0d, 0x1b1b1b12, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b,430	  0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b,431	  0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0xff1b1b1b },432	{ 0x01020043, 0x01010101, 0x01010102, 0x02020202, 0x03030503,433	  0x06030202, 0x05030404, 0x07070607, 0x06070607, 0x090b0908,434	  0x080a0808, 0x0d0a0706, 0x0c0b0a0a, 0x070c0d0c, 0x0e0f0e09,435	  0x0c0b0f0c, 0xdbff0c0c, 0x03014300, 0x03040303, 0x04040804,436	  0x0a0c1208, 0x1212120c, 0x12121212, 0x12121212, 0x12121212,437	  0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212,438	  0x12121212, 0x12121212, 0x12121212, 0xff121212 },439	{ 0x01020043, 0x01010101, 0x01010102, 0x02020202, 0x03030503,440	  0x06030202, 0x05030404, 0x07070607, 0x06070607, 0x090b0908,441	  0x080a0808, 0x0d0a0706, 0x0c0b0a0a, 0x070c0d0c, 0x0e0f0e09,442	  0x0c0b0f0c, 0xdbff0c0c, 0x02014300, 0x03030202, 0x04040703,443	  0x080a0f07, 0x0f0f0f0a, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f,444	  0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f,445	  0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xff0f0f0f },446	{ 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x02020302,447	  0x04020202, 0x03020303, 0x05050405, 0x05050405, 0x07080606,448	  0x06080606, 0x0a070505, 0x09080807, 0x05090909, 0x0a0b0a07,449	  0x09080b09, 0xdbff0909, 0x02014300, 0x02030202, 0x03030503,450	  0x07080c05, 0x0c0c0c08, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,451	  0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,452	  0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xff0c0c0c },453	{ 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x01010201,454	  0x03010101, 0x02010202, 0x03030303, 0x03030303, 0x04050404,455	  0x04050404, 0x06050303, 0x06050505, 0x03060606, 0x07070704,456	  0x06050706, 0xdbff0606, 0x01014300, 0x01020101, 0x02020402,457	  0x05060904, 0x09090906, 0x09090909, 0x09090909, 0x09090909,458	  0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909,459	  0x09090909, 0x09090909, 0x09090909, 0xff090909 },460	{ 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x01010101,461	  0x01010101, 0x01010101, 0x01010101, 0x01010101, 0x02020202,462	  0x02020202, 0x03020101, 0x03020202, 0x01030303, 0x03030302,463	  0x03020303, 0xdbff0403, 0x01014300, 0x01010101, 0x01010201,464	  0x03040602, 0x06060604, 0x06060606, 0x06060606, 0x06060606,465	  0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,466	  0x06060606, 0x06060606, 0x06060606, 0xff060606 }467};468 469static const struct v4l2_dv_timings_cap aspeed_video_timings_cap = {470	.type = V4L2_DV_BT_656_1120,471	.bt = {472		.min_width = MIN_WIDTH,473		.max_width = MAX_WIDTH,474		.min_height = MIN_HEIGHT,475		.max_height = MAX_HEIGHT,476		.min_pixelclock = 6574080, /* 640 x 480 x 24Hz */477		.max_pixelclock = 138240000, /* 1920 x 1200 x 60Hz */478		.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |479			V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,480		.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |481			V4L2_DV_BT_CAP_REDUCED_BLANKING |482			V4L2_DV_BT_CAP_CUSTOM,483	},484};485 486static const char * const format_str[] = {"Standard JPEG",487	"Aspeed JPEG"};488 489static unsigned int debug;490 491static bool aspeed_video_alloc_buf(struct aspeed_video *video,492				   struct aspeed_video_addr *addr,493				   unsigned int size);494 495static void aspeed_video_free_buf(struct aspeed_video *video,496				  struct aspeed_video_addr *addr);497 498static void aspeed_video_init_jpeg_table(u32 *table, bool yuv420)499{500	int i;501	unsigned int base;502 503	for (i = 0; i < ASPEED_VIDEO_JPEG_NUM_QUALITIES; i++) {504		base = 256 * i;	/* AST HW requires this header spacing */505		memcpy(&table[base], aspeed_video_jpeg_header,506		       sizeof(aspeed_video_jpeg_header));507 508		base += ASPEED_VIDEO_JPEG_HEADER_SIZE;509		memcpy(&table[base], aspeed_video_jpeg_dct[i],510		       sizeof(aspeed_video_jpeg_dct[i]));511 512		base += ASPEED_VIDEO_JPEG_DCT_SIZE;513		memcpy(&table[base], aspeed_video_jpeg_quant,514		       sizeof(aspeed_video_jpeg_quant));515 516		if (yuv420)517			table[base + 2] = 0x00220103;518	}519}520 521// just update jpeg dct table per 420/444522static void aspeed_video_update_jpeg_table(u32 *table, bool yuv420)523{524	int i;525	unsigned int base;526 527	for (i = 0; i < ASPEED_VIDEO_JPEG_NUM_QUALITIES; i++) {528		base = 256 * i;	/* AST HW requires this header spacing */529		base += ASPEED_VIDEO_JPEG_HEADER_SIZE +530			ASPEED_VIDEO_JPEG_DCT_SIZE;531 532		table[base + 2] = (yuv420) ? 0x00220103 : 0x00110103;533	}534}535 536static void aspeed_video_update(struct aspeed_video *video, u32 reg, u32 clear,537				u32 bits)538{539	u32 t = readl(video->base + reg);540	u32 before = t;541 542	t &= ~clear;543	t |= bits;544	writel(t, video->base + reg);545	v4l2_dbg(3, debug, &video->v4l2_dev, "update %03x[%08x -> %08x]\n",546		 reg, before, readl(video->base + reg));547}548 549static u32 aspeed_video_read(struct aspeed_video *video, u32 reg)550{551	u32 t = readl(video->base + reg);552 553	v4l2_dbg(3, debug, &video->v4l2_dev, "read %03x[%08x]\n", reg, t);554	return t;555}556 557static void aspeed_video_write(struct aspeed_video *video, u32 reg, u32 val)558{559	writel(val, video->base + reg);560	v4l2_dbg(3, debug, &video->v4l2_dev, "write %03x[%08x]\n", reg,561		 readl(video->base + reg));562}563 564static void update_perf(struct aspeed_video_perf *p)565{566	struct aspeed_video *v = container_of(p, struct aspeed_video,567					      perf);568 569	p->duration =570		ktime_to_ms(ktime_sub(ktime_get(),  p->last_sample));571	p->totaltime += p->duration;572 573	p->duration_max = max(p->duration, p->duration_max);574	p->duration_min = min(p->duration, p->duration_min);575	v4l2_dbg(2, debug, &v->v4l2_dev, "time consumed: %d ms\n",576		 p->duration);577}578 579static int aspeed_video_start_frame(struct aspeed_video *video)580{581	dma_addr_t addr;582	unsigned long flags;583	struct aspeed_video_buffer *buf;584	u32 seq_ctrl = aspeed_video_read(video, VE_SEQ_CTRL);585	bool bcd_buf_need = (video->format != VIDEO_FMT_STANDARD);586 587	if (video->v4l2_input_status) {588		v4l2_dbg(1, debug, &video->v4l2_dev, "No signal; don't start frame\n");589		return 0;590	}591 592	if (!(seq_ctrl & VE_SEQ_CTRL_COMP_BUSY) ||593	    !(seq_ctrl & VE_SEQ_CTRL_CAP_BUSY)) {594		v4l2_dbg(1, debug, &video->v4l2_dev, "Engine busy; don't start frame\n");595		return -EBUSY;596	}597 598	if (bcd_buf_need && !video->bcd.size) {599		if (!aspeed_video_alloc_buf(video, &video->bcd,600					    VE_BCD_BUFF_SIZE)) {601			dev_err(video->dev, "Failed to allocate BCD buffer\n");602			dev_err(video->dev, "don't start frame\n");603			return -ENOMEM;604		}605		aspeed_video_write(video, VE_BCD_ADDR, video->bcd.dma);606		v4l2_dbg(1, debug, &video->v4l2_dev, "bcd addr(%pad) size(%d)\n",607			 &video->bcd.dma, video->bcd.size);608	} else if (!bcd_buf_need && video->bcd.size) {609		aspeed_video_free_buf(video, &video->bcd);610	}611 612	spin_lock_irqsave(&video->lock, flags);613	buf = list_first_entry_or_null(&video->buffers,614				       struct aspeed_video_buffer, link);615	if (!buf) {616		spin_unlock_irqrestore(&video->lock, flags);617		v4l2_dbg(1, debug, &video->v4l2_dev, "No buffers; don't start frame\n");618		return -EPROTO;619	}620 621	set_bit(VIDEO_FRAME_INPRG, &video->flags);622	addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);623	spin_unlock_irqrestore(&video->lock, flags);624 625	aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);626	aspeed_video_write(video, VE_COMP_OFFSET, 0);627	aspeed_video_write(video, VE_COMP_ADDR, addr);628 629	aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,630			    VE_INTERRUPT_COMP_COMPLETE);631 632	video->perf.last_sample = ktime_get();633 634	aspeed_video_update(video, VE_SEQ_CTRL, 0,635			    VE_SEQ_CTRL_TRIG_CAPTURE | VE_SEQ_CTRL_TRIG_COMP);636 637	return 0;638}639 640static void aspeed_video_enable_mode_detect(struct aspeed_video *video)641{642	/* Enable mode detect interrupts */643	aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,644			    VE_INTERRUPT_MODE_DETECT);645 646	/* Disable mode detect in order to re-trigger */647	aspeed_video_update(video, VE_SEQ_CTRL,648			    VE_SEQ_CTRL_TRIG_MODE_DET, 0);649 650	/* Trigger mode detect */651	aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_TRIG_MODE_DET);652}653 654static void aspeed_video_off(struct aspeed_video *video)655{656	if (!test_bit(VIDEO_CLOCKS_ON, &video->flags))657		return;658 659	/* Disable interrupts */660	aspeed_video_write(video, VE_INTERRUPT_CTRL, 0);661	aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);662 663	/* Turn off the relevant clocks */664	clk_disable(video->eclk);665	clk_disable(video->vclk);666 667	clear_bit(VIDEO_CLOCKS_ON, &video->flags);668}669 670static void aspeed_video_on(struct aspeed_video *video)671{672	if (test_bit(VIDEO_CLOCKS_ON, &video->flags))673		return;674 675	/* Turn on the relevant clocks */676	clk_enable(video->vclk);677	clk_enable(video->eclk);678 679	set_bit(VIDEO_CLOCKS_ON, &video->flags);680}681 682static void aspeed_video_bufs_done(struct aspeed_video *video,683				   enum vb2_buffer_state state)684{685	unsigned long flags;686	struct aspeed_video_buffer *buf;687 688	spin_lock_irqsave(&video->lock, flags);689	list_for_each_entry(buf, &video->buffers, link)690		vb2_buffer_done(&buf->vb.vb2_buf, state);691	INIT_LIST_HEAD(&video->buffers);692	spin_unlock_irqrestore(&video->lock, flags);693}694 695static void aspeed_video_irq_res_change(struct aspeed_video *video, ulong delay)696{697	v4l2_dbg(1, debug, &video->v4l2_dev, "Resolution changed; resetting\n");698 699	set_bit(VIDEO_RES_CHANGE, &video->flags);700	clear_bit(VIDEO_FRAME_INPRG, &video->flags);701 702	video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;703 704	aspeed_video_off(video);705	aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);706 707	schedule_delayed_work(&video->res_work, delay);708}709 710static void aspeed_video_swap_src_buf(struct aspeed_video *v)711{712	if (v->format == VIDEO_FMT_STANDARD)713		return;714 715	/* Reset bcd buffer to have a full frame update every 8 frames.  */716	if (IS_ALIGNED(v->sequence, 8))717		memset((u8 *)v->bcd.virt, 0x00, VE_BCD_BUFF_SIZE);718 719	if (v->sequence & 0x01) {720		aspeed_video_write(v, VE_SRC0_ADDR, v->srcs[1].dma);721		aspeed_video_write(v, VE_SRC1_ADDR, v->srcs[0].dma);722	} else {723		aspeed_video_write(v, VE_SRC0_ADDR, v->srcs[0].dma);724		aspeed_video_write(v, VE_SRC1_ADDR, v->srcs[1].dma);725	}726}727 728static irqreturn_t aspeed_video_irq(int irq, void *arg)729{730	struct aspeed_video *video = arg;731	u32 sts = aspeed_video_read(video, VE_INTERRUPT_STATUS);732 733	/*734	 * Hardware sometimes asserts interrupts that we haven't actually735	 * enabled; ignore them if so.736	 */737	sts &= aspeed_video_read(video, VE_INTERRUPT_CTRL);738 739	v4l2_dbg(2, debug, &video->v4l2_dev, "irq sts=%#x %s%s%s%s\n", sts,740		 sts & VE_INTERRUPT_MODE_DETECT_WD ? ", unlock" : "",741		 sts & VE_INTERRUPT_MODE_DETECT ? ", lock" : "",742		 sts & VE_INTERRUPT_CAPTURE_COMPLETE ? ", capture-done" : "",743		 sts & VE_INTERRUPT_COMP_COMPLETE ? ", comp-done" : "");744 745	/*746	 * Resolution changed or signal was lost; reset the engine and747	 * re-initialize748	 */749	if (sts & VE_INTERRUPT_MODE_DETECT_WD) {750		aspeed_video_irq_res_change(video, 0);751		return IRQ_HANDLED;752	}753 754	if (sts & VE_INTERRUPT_MODE_DETECT) {755		if (test_bit(VIDEO_RES_DETECT, &video->flags)) {756			aspeed_video_update(video, VE_INTERRUPT_CTRL,757					    VE_INTERRUPT_MODE_DETECT, 0);758			aspeed_video_write(video, VE_INTERRUPT_STATUS,759					   VE_INTERRUPT_MODE_DETECT);760			sts &= ~VE_INTERRUPT_MODE_DETECT;761			set_bit(VIDEO_MODE_DETECT_DONE, &video->flags);762			wake_up_interruptible_all(&video->wait);763		} else {764			/*765			 * Signal acquired while NOT doing resolution766			 * detection; reset the engine and re-initialize767			 */768			aspeed_video_irq_res_change(video,769						    RESOLUTION_CHANGE_DELAY);770			return IRQ_HANDLED;771		}772	}773 774	if (sts & VE_INTERRUPT_COMP_COMPLETE) {775		struct aspeed_video_buffer *buf;776		bool empty = true;777		u32 frame_size = aspeed_video_read(video,778						   video->comp_size_read);779 780		update_perf(&video->perf);781 782		spin_lock(&video->lock);783		clear_bit(VIDEO_FRAME_INPRG, &video->flags);784		buf = list_first_entry_or_null(&video->buffers,785					       struct aspeed_video_buffer,786					       link);787		if (buf) {788			vb2_set_plane_payload(&buf->vb.vb2_buf, 0, frame_size);789 790			/*791			 * aspeed_jpeg requires continuous update.792			 * On the contrary, standard jpeg can keep last buffer793			 * to always have the latest result.794			 */795			if (video->format == VIDEO_FMT_STANDARD &&796			    list_is_last(&buf->link, &video->buffers)) {797				empty = false;798				v4l2_dbg(1, debug, &video->v4l2_dev, "skip to keep last frame updated\n");799			} else {800				buf->vb.vb2_buf.timestamp = ktime_get_ns();801				buf->vb.sequence = video->sequence++;802				buf->vb.field = V4L2_FIELD_NONE;803				vb2_buffer_done(&buf->vb.vb2_buf,804						VB2_BUF_STATE_DONE);805				list_del(&buf->link);806				empty = list_empty(&video->buffers);807			}808		}809		spin_unlock(&video->lock);810 811		aspeed_video_update(video, VE_SEQ_CTRL,812				    VE_SEQ_CTRL_TRIG_CAPTURE |813				    VE_SEQ_CTRL_FORCE_IDLE |814				    VE_SEQ_CTRL_TRIG_COMP, 0);815		aspeed_video_update(video, VE_INTERRUPT_CTRL,816				    VE_INTERRUPT_COMP_COMPLETE, 0);817		aspeed_video_write(video, VE_INTERRUPT_STATUS,818				   VE_INTERRUPT_COMP_COMPLETE);819		sts &= ~VE_INTERRUPT_COMP_COMPLETE;820 821		aspeed_video_swap_src_buf(video);822 823		if (test_bit(VIDEO_STREAMING, &video->flags) && !empty)824			aspeed_video_start_frame(video);825	}826 827	return sts ? IRQ_NONE : IRQ_HANDLED;828}829 830static void aspeed_video_check_and_set_polarity(struct aspeed_video *video)831{832	int i;833	int hsync_counter = 0;834	int vsync_counter = 0;835	u32 sts, ctrl;836 837	for (i = 0; i < NUM_POLARITY_CHECKS; ++i) {838		sts = aspeed_video_read(video, VE_MODE_DETECT_STATUS);839		if (sts & VE_MODE_DETECT_STATUS_VSYNC)840			vsync_counter--;841		else842			vsync_counter++;843 844		if (sts & VE_MODE_DETECT_STATUS_HSYNC)845			hsync_counter--;846		else847			hsync_counter++;848	}849 850	ctrl = aspeed_video_read(video, VE_CTRL);851 852	if (hsync_counter < 0) {853		ctrl |= VE_CTRL_HSYNC_POL;854		video->detected_timings.polarities &=855			~V4L2_DV_HSYNC_POS_POL;856	} else {857		ctrl &= ~VE_CTRL_HSYNC_POL;858		video->detected_timings.polarities |=859			V4L2_DV_HSYNC_POS_POL;860	}861 862	if (vsync_counter < 0) {863		ctrl |= VE_CTRL_VSYNC_POL;864		video->detected_timings.polarities &=865			~V4L2_DV_VSYNC_POS_POL;866	} else {867		ctrl &= ~VE_CTRL_VSYNC_POL;868		video->detected_timings.polarities |=869			V4L2_DV_VSYNC_POS_POL;870	}871 872	aspeed_video_write(video, VE_CTRL, ctrl);873}874 875static bool aspeed_video_alloc_buf(struct aspeed_video *video,876				   struct aspeed_video_addr *addr,877				   unsigned int size)878{879	addr->virt = dma_alloc_coherent(video->dev, size, &addr->dma,880					GFP_KERNEL);881	if (!addr->virt)882		return false;883 884	addr->size = size;885	return true;886}887 888static void aspeed_video_free_buf(struct aspeed_video *video,889				  struct aspeed_video_addr *addr)890{891	dma_free_coherent(video->dev, addr->size, addr->virt, addr->dma);892	addr->size = 0;893	addr->dma = 0ULL;894	addr->virt = NULL;895}896 897/*898 * Get the minimum HW-supported compression buffer size for the frame size.899 * Assume worst-case JPEG compression size is 1/8 raw size. This should be900 * plenty even for maximum quality; any worse and the engine will simply return901 * incomplete JPEGs.902 */903static void aspeed_video_calc_compressed_size(struct aspeed_video *video,904					      unsigned int frame_size)905{906	int i, j;907	u32 compression_buffer_size_reg = 0;908	unsigned int size;909	const unsigned int num_compression_packets = 4;910	const unsigned int compression_packet_size = 1024;911	const unsigned int max_compressed_size = frame_size / 2; /* 4bpp / 8 */912 913	video->max_compressed_size = UINT_MAX;914 915	for (i = 0; i < 6; ++i) {916		for (j = 0; j < 8; ++j) {917			size = (num_compression_packets << i) *918				(compression_packet_size << j);919			if (size < max_compressed_size)920				continue;921 922			if (size < video->max_compressed_size) {923				compression_buffer_size_reg = (i << 3) | j;924				video->max_compressed_size = size;925			}926		}927	}928 929	aspeed_video_write(video, VE_STREAM_BUF_SIZE,930			   compression_buffer_size_reg);931 932	v4l2_dbg(1, debug, &video->v4l2_dev, "Max compressed size: %#x\n",933		 video->max_compressed_size);934}935 936/*937 * Update v4l2_bt_timings per current status.938 * frame_top/frame_bottom/frame_left/frame_right need to be ready.939 *940 * The following registers start counting from sync's rising edge:941 * 1. VR090: frame edge's left and right942 * 2. VR094: frame edge's top and bottom943 * 3. VR09C: counting from sync's rising edge to falling edge944 *945 * [Vertical timing]946 *             +--+     +-------------------+     +--+947 *             |  |     |     v i d e o     |     |  |948 *          +--+  +-----+                   +-----+  +---+949 *        vsync+--+950 *    frame_top+--------+951 * frame_bottom+----------------------------+952 *953 *                   +-------------------+954 *                   |     v i d e o     |955 *       +--+  +-----+                   +-----+  +---+956 *          |  |                               |  |957 *          +--+                               +--+958 *        vsync+-------------------------------+959 *    frame_top+-----+960 * frame_bottom+-------------------------+961 *962 * [Horizontal timing]963 *             +--+     +-------------------+     +--+964 *             |  |     |     v i d e o     |     |  |965 *          +--+  +-----+                   +-----+  +---+966 *        hsync+--+967 *   frame_left+--------+968 *  frame_right+----------------------------+969 *970 *                   +-------------------+971 *                   |     v i d e o     |972 *       +--+  +-----+                   +-----+  +---+973 *          |  |                               |  |974 *          +--+                               +--+975 *        hsync+-------------------------------+976 *   frame_left+-----+977 *  frame_right+-------------------------+978 *979 * @v: the struct of aspeed_video980 * @det: v4l2_bt_timings to be updated.981 */982static void aspeed_video_get_timings(struct aspeed_video *v,983				     struct v4l2_bt_timings *det)984{985	u32 mds, sync, htotal, vtotal, vsync, hsync;986 987	mds = aspeed_video_read(v, VE_MODE_DETECT_STATUS);988	sync = aspeed_video_read(v, VE_SYNC_STATUS);989	htotal = aspeed_video_read(v, VE_H_TOTAL_PIXELS);990	vtotal = FIELD_GET(VE_MODE_DETECT_V_LINES, mds);991	vsync = FIELD_GET(VE_SYNC_STATUS_VSYNC, sync);992	hsync = FIELD_GET(VE_SYNC_STATUS_HSYNC, sync);993 994	/*995	 * This is a workaround for polarity detection.996	 * Because ast-soc counts sync from sync's rising edge, the reg value997	 * of sync would be larger than video's active area if negative.998	 */999	if (vsync > det->height)1000		det->polarities &= ~V4L2_DV_VSYNC_POS_POL;1001	else1002		det->polarities |= V4L2_DV_VSYNC_POS_POL;1003	if (hsync > det->width)1004		det->polarities &= ~V4L2_DV_HSYNC_POS_POL;1005	else1006		det->polarities |= V4L2_DV_HSYNC_POS_POL;1007 1008	if (det->polarities & V4L2_DV_VSYNC_POS_POL) {1009		det->vbackporch = v->frame_top - vsync;1010		det->vfrontporch = vtotal - v->frame_bottom;1011		det->vsync = vsync;1012	} else {1013		det->vbackporch = v->frame_top;1014		det->vfrontporch = vsync - v->frame_bottom;1015		det->vsync = vtotal - vsync;1016	}1017 1018	if (det->polarities & V4L2_DV_HSYNC_POS_POL) {1019		det->hbackporch = v->frame_left - hsync;1020		det->hfrontporch = htotal - v->frame_right;1021		det->hsync = hsync;1022	} else {1023		det->hbackporch = v->frame_left;1024		det->hfrontporch = hsync - v->frame_right;1025		det->hsync = htotal - hsync;1026	}1027}1028 1029#define res_check(v) test_and_clear_bit(VIDEO_MODE_DETECT_DONE, &(v)->flags)1030 1031static void aspeed_video_get_resolution(struct aspeed_video *video)1032{1033	bool invalid_resolution = true;1034	int rc;1035	int tries = 0;1036	u32 mds;1037	u32 src_lr_edge;1038	u32 src_tb_edge;1039	struct v4l2_bt_timings *det = &video->detected_timings;1040 1041	det->width = MIN_WIDTH;1042	det->height = MIN_HEIGHT;1043	video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;1044	memset(&video->perf, 0, sizeof(video->perf));1045 1046	do {1047		if (tries) {1048			set_current_state(TASK_INTERRUPTIBLE);1049			if (schedule_timeout(INVALID_RESOLUTION_DELAY))1050				return;1051		}1052 1053		set_bit(VIDEO_RES_DETECT, &video->flags);1054		aspeed_video_update(video, VE_CTRL,1055				    VE_CTRL_VSYNC_POL | VE_CTRL_HSYNC_POL, 0);1056		aspeed_video_enable_mode_detect(video);1057 1058		rc = wait_event_interruptible_timeout(video->wait,1059						      res_check(video),1060						      MODE_DETECT_TIMEOUT);1061		if (!rc) {1062			v4l2_dbg(1, debug, &video->v4l2_dev, "Timed out; first mode detect\n");1063			clear_bit(VIDEO_RES_DETECT, &video->flags);1064			return;1065		}1066 1067		mds = aspeed_video_read(video, VE_MODE_DETECT_STATUS);1068		// try detection again if current signal isn't stable1069		if (!(mds & VE_MODE_DETECT_H_STABLE) ||1070		    !(mds & VE_MODE_DETECT_V_STABLE) ||1071		    (mds & VE_MODE_DETECT_EXTSRC_ADC))1072			continue;1073 1074		aspeed_video_check_and_set_polarity(video);1075 1076		aspeed_video_enable_mode_detect(video);1077 1078		rc = wait_event_interruptible_timeout(video->wait,1079						      res_check(video),1080						      MODE_DETECT_TIMEOUT);1081		clear_bit(VIDEO_RES_DETECT, &video->flags);1082		if (!rc) {1083			v4l2_dbg(1, debug, &video->v4l2_dev, "Timed out; second mode detect\n");1084			return;1085		}1086 1087		src_lr_edge = aspeed_video_read(video, VE_SRC_LR_EDGE_DET);1088		src_tb_edge = aspeed_video_read(video, VE_SRC_TB_EDGE_DET);1089 1090		video->frame_bottom = FIELD_GET(VE_SRC_TB_EDGE_DET_BOT, src_tb_edge);1091		video->frame_top = FIELD_GET(VE_SRC_TB_EDGE_DET_TOP, src_tb_edge);1092 1093		if (video->frame_top > video->frame_bottom)1094			continue;1095 1096		video->frame_right = FIELD_GET(VE_SRC_LR_EDGE_DET_RT, src_lr_edge);1097		video->frame_left = FIELD_GET(VE_SRC_LR_EDGE_DET_LEFT, src_lr_edge);1098 1099		if (video->frame_left > video->frame_right)1100			continue;1101 1102		invalid_resolution = false;1103	} while (invalid_resolution && (tries++ < INVALID_RESOLUTION_RETRIES));1104 1105	if (invalid_resolution) {1106		v4l2_dbg(1, debug, &video->v4l2_dev, "Invalid resolution detected\n");1107		return;1108	}1109 1110	det->height = (video->frame_bottom - video->frame_top) + 1;1111	det->width = (video->frame_right - video->frame_left) + 1;1112	video->v4l2_input_status = 0;1113 1114	aspeed_video_get_timings(video, det);1115 1116	/*1117	 * Enable mode-detect watchdog, resolution-change watchdog and1118	 * automatic compression after frame capture.1119	 */1120	aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,1121			    VE_INTERRUPT_MODE_DETECT_WD);1122	aspeed_video_update(video, VE_SEQ_CTRL, 0,1123			    VE_SEQ_CTRL_AUTO_COMP | VE_SEQ_CTRL_EN_WATCHDOG);1124 1125	v4l2_dbg(1, debug, &video->v4l2_dev, "Got resolution: %dx%d\n",1126		 det->width, det->height);1127}1128 1129static void aspeed_video_set_resolution(struct aspeed_video *video)1130{1131	struct v4l2_bt_timings *act = &video->active_timings;1132	unsigned int size = act->width * ALIGN(act->height, 8);1133 1134	/* Set capture/compression frame sizes */1135	aspeed_video_calc_compressed_size(video, size);1136 1137	if (!IS_ALIGNED(act->width, 64)) {1138		/*1139		 * This is a workaround to fix a AST2500 silicon bug on A1 and1140		 * A2 revisions. Since it doesn't break capturing operation of1141		 * other revisions, use it for all revisions without checking1142		 * the revision ID. It picked new width which is a very next1143		 * 64-pixels aligned value to minimize memory bandwidth1144		 * and to get better access speed from video engine.1145		 */1146		u32 width = ALIGN(act->width, 64);1147 1148		aspeed_video_write(video, VE_CAP_WINDOW, width << 16 | act->height);1149		size = width * ALIGN(act->height, 8);1150	} else {1151		aspeed_video_write(video, VE_CAP_WINDOW,1152				   act->width << 16 | act->height);1153	}1154	aspeed_video_write(video, VE_COMP_WINDOW,1155			   act->width << 16 | act->height);1156	aspeed_video_write(video, VE_SRC_SCANLINE_OFFSET, act->width * 4);1157 1158	/* Don't use direct mode below 1024 x 768 (irqs don't fire) */1159	if (size < DIRECT_FETCH_THRESHOLD) {1160		v4l2_dbg(1, debug, &video->v4l2_dev, "Capture: Sync Mode\n");1161		aspeed_video_write(video, VE_TGS_0,1162				   FIELD_PREP(VE_TGS_FIRST,1163					      video->frame_left - 1) |1164				   FIELD_PREP(VE_TGS_LAST,1165					      video->frame_right));1166		aspeed_video_write(video, VE_TGS_1,1167				   FIELD_PREP(VE_TGS_FIRST, video->frame_top) |1168				   FIELD_PREP(VE_TGS_LAST,1169					      video->frame_bottom + 1));1170		aspeed_video_update(video, VE_CTRL,1171				    VE_CTRL_INT_DE | VE_CTRL_DIRECT_FETCH,1172				    VE_CTRL_INT_DE);1173	} else {1174		v4l2_dbg(1, debug, &video->v4l2_dev, "Capture: Direct Mode\n");1175		aspeed_video_update(video, VE_CTRL,1176				    VE_CTRL_INT_DE | VE_CTRL_DIRECT_FETCH,1177				    VE_CTRL_DIRECT_FETCH);1178	}1179 1180	size *= 4;1181 1182	if (size != video->srcs[0].size) {1183		if (video->srcs[0].size)1184			aspeed_video_free_buf(video, &video->srcs[0]);1185		if (video->srcs[1].size)1186			aspeed_video_free_buf(video, &video->srcs[1]);1187 1188		if (!aspeed_video_alloc_buf(video, &video->srcs[0], size))1189			goto err_mem;1190		if (!aspeed_video_alloc_buf(video, &video->srcs[1], size))1191			goto err_mem;1192 1193		v4l2_dbg(1, debug, &video->v4l2_dev, "src buf0 addr(%pad) size(%d)\n",1194			 &video->srcs[0].dma, video->srcs[0].size);1195		v4l2_dbg(1, debug, &video->v4l2_dev, "src buf1 addr(%pad) size(%d)\n",1196			 &video->srcs[1].dma, video->srcs[1].size);1197		aspeed_video_write(video, VE_SRC0_ADDR, video->srcs[0].dma);1198		aspeed_video_write(video, VE_SRC1_ADDR, video->srcs[1].dma);1199	}1200 1201	return;1202 1203err_mem:1204	dev_err(video->dev, "Failed to allocate source buffers\n");1205 1206	if (video->srcs[0].size)1207		aspeed_video_free_buf(video, &video->srcs[0]);1208}1209 1210static void aspeed_video_update_regs(struct aspeed_video *video)1211{1212	u8 jpeg_hq_quality = clamp((int)video->jpeg_hq_quality - 1, 0,1213				   ASPEED_VIDEO_JPEG_NUM_QUALITIES - 1);1214	u32 comp_ctrl =	FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |1215		FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10) |1216		FIELD_PREP(VE_COMP_CTRL_EN_HQ, video->hq_mode) |1217		FIELD_PREP(VE_COMP_CTRL_HQ_DCT_LUM, jpeg_hq_quality) |1218		FIELD_PREP(VE_COMP_CTRL_HQ_DCT_CHR, jpeg_hq_quality | 0x10);1219	u32 ctrl = 0;1220	u32 seq_ctrl = 0;1221 1222	v4l2_dbg(1, debug, &video->v4l2_dev, "framerate(%d)\n",1223		 video->frame_rate);1224	v4l2_dbg(1, debug, &video->v4l2_dev, "jpeg format(%s) subsample(%s)\n",1225		 format_str[video->format],1226		 video->yuv420 ? "420" : "444");1227	v4l2_dbg(1, debug, &video->v4l2_dev, "compression quality(%d)\n",1228		 video->jpeg_quality);1229	v4l2_dbg(1, debug, &video->v4l2_dev, "hq_mode(%s) hq_quality(%d)\n",1230		 video->hq_mode ? "on" : "off", video->jpeg_hq_quality);1231 1232	if (video->format == VIDEO_FMT_ASPEED)1233		aspeed_video_update(video, VE_BCD_CTRL, 0, VE_BCD_CTRL_EN_BCD);1234	else1235		aspeed_video_update(video, VE_BCD_CTRL, VE_BCD_CTRL_EN_BCD, 0);1236 1237	if (video->frame_rate)1238		ctrl |= FIELD_PREP(VE_CTRL_FRC, video->frame_rate);1239 1240	if (video->format == VIDEO_FMT_STANDARD) {1241		comp_ctrl &= ~FIELD_PREP(VE_COMP_CTRL_EN_HQ, video->hq_mode);1242		seq_ctrl |= video->jpeg_mode;1243	}1244 1245	if (video->yuv420)1246		seq_ctrl |= VE_SEQ_CTRL_YUV420;1247 1248	if (video->jpeg.virt)1249		aspeed_video_update_jpeg_table(video->jpeg.virt, video->yuv420);1250 1251	/* Set control registers */1252	aspeed_video_update(video, VE_SEQ_CTRL,1253			    video->jpeg_mode | VE_SEQ_CTRL_YUV420,1254			    seq_ctrl);1255	aspeed_video_update(video, VE_CTRL, VE_CTRL_FRC, ctrl);1256	aspeed_video_update(video, VE_COMP_CTRL,1257			    VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR |1258			    VE_COMP_CTRL_EN_HQ | VE_COMP_CTRL_HQ_DCT_LUM |1259			    VE_COMP_CTRL_HQ_DCT_CHR | VE_COMP_CTRL_VQ_4COLOR |1260			    VE_COMP_CTRL_VQ_DCT_ONLY,1261			    comp_ctrl);1262}1263 1264static void aspeed_video_init_regs(struct aspeed_video *video)1265{1266	u32 ctrl = VE_CTRL_AUTO_OR_CURSOR |1267		FIELD_PREP(VE_CTRL_CAPTURE_FMT, VIDEO_CAP_FMT_YUV_FULL_SWING);1268 1269	/* Unlock VE registers */1270	aspeed_video_write(video, VE_PROTECTION_KEY, VE_PROTECTION_KEY_UNLOCK);1271 1272	/* Disable interrupts */1273	aspeed_video_write(video, VE_INTERRUPT_CTRL, 0);1274	aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);1275 1276	/* Clear the offset */1277	aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);1278	aspeed_video_write(video, VE_COMP_OFFSET, 0);1279 1280	aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg.dma);1281 1282	/* Set control registers */1283	aspeed_video_write(video, VE_CTRL, ctrl);1284	aspeed_video_write(video, VE_COMP_CTRL, VE_COMP_CTRL_RSVD);1285 1286	/* Don't downscale */1287	aspeed_video_write(video, VE_SCALING_FACTOR, 0x10001000);1288	aspeed_video_write(video, VE_SCALING_FILTER0, 0x00200000);1289	aspeed_video_write(video, VE_SCALING_FILTER1, 0x00200000);1290	aspeed_video_write(video, VE_SCALING_FILTER2, 0x00200000);1291	aspeed_video_write(video, VE_SCALING_FILTER3, 0x00200000);1292 1293	/* Set mode detection defaults */1294	aspeed_video_write(video, VE_MODE_DETECT,1295			   FIELD_PREP(VE_MODE_DT_HOR_TOLER, 2) |1296			   FIELD_PREP(VE_MODE_DT_VER_TOLER, 2) |1297			   FIELD_PREP(VE_MODE_DT_HOR_STABLE, 6) |1298			   FIELD_PREP(VE_MODE_DT_VER_STABLE, 6) |1299			   FIELD_PREP(VE_MODE_DT_EDG_THROD, 0x65));1300 1301	aspeed_video_write(video, VE_BCD_CTRL, 0);1302}1303 1304static void aspeed_video_start(struct aspeed_video *video)1305{1306	aspeed_video_on(video);1307 1308	aspeed_video_init_regs(video);1309 1310	/* Resolution set to 640x480 if no signal found */1311	aspeed_video_get_resolution(video);1312 1313	/* Set timings since the device is being opened for the first time */1314	video->active_timings = video->detected_timings;1315	aspeed_video_set_resolution(video);1316 1317	video->pix_fmt.width = video->active_timings.width;1318	video->pix_fmt.height = video->active_timings.height;1319	video->pix_fmt.sizeimage = video->max_compressed_size;1320}1321 1322static void aspeed_video_stop(struct aspeed_video *video)1323{1324	set_bit(VIDEO_STOPPED, &video->flags);1325	cancel_delayed_work_sync(&video->res_work);1326 1327	aspeed_video_off(video);1328 1329	if (video->srcs[0].size)1330		aspeed_video_free_buf(video, &video->srcs[0]);1331 1332	if (video->srcs[1].size)1333		aspeed_video_free_buf(video, &video->srcs[1]);1334 1335	if (video->bcd.size)1336		aspeed_video_free_buf(video, &video->bcd);1337 1338	video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;1339	video->flags = 0;1340}1341 1342static int aspeed_video_querycap(struct file *file, void *fh,1343				 struct v4l2_capability *cap)1344{1345	strscpy(cap->driver, DEVICE_NAME, sizeof(cap->driver));1346	strscpy(cap->card, "Aspeed Video Engine", sizeof(cap->card));1347	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",1348		 DEVICE_NAME);1349 1350	return 0;1351}1352 1353static int aspeed_video_enum_format(struct file *file, void *fh,1354				    struct v4l2_fmtdesc *f)1355{1356	struct aspeed_video *video = video_drvdata(file);1357 1358	if (f->index)1359		return -EINVAL;1360 1361	f->pixelformat = video->pix_fmt.pixelformat;1362 1363	return 0;1364}1365 1366static int aspeed_video_get_format(struct file *file, void *fh,1367				   struct v4l2_format *f)1368{1369	struct aspeed_video *video = video_drvdata(file);1370 1371	f->fmt.pix = video->pix_fmt;1372 1373	return 0;1374}1375 1376static int aspeed_video_set_format(struct file *file, void *fh,1377				   struct v4l2_format *f)1378{1379	struct aspeed_video *video = video_drvdata(file);1380 1381	if (vb2_is_busy(&video->queue))1382		return -EBUSY;1383 1384	switch (f->fmt.pix.pixelformat) {1385	case V4L2_PIX_FMT_JPEG:1386		video->format = VIDEO_FMT_STANDARD;1387		break;1388	case V4L2_PIX_FMT_AJPG:1389		video->format = VIDEO_FMT_ASPEED;1390		break;1391	default:1392		return -EINVAL;1393	}1394	video->pix_fmt.pixelformat = f->fmt.pix.pixelformat;1395 1396	return 0;1397}1398 1399static int aspeed_video_enum_input(struct file *file, void *fh,1400				   struct v4l2_input *inp)1401{1402	struct aspeed_video *video = video_drvdata(file);1403 1404	if (inp->index)1405		return -EINVAL;1406 1407	strscpy(inp->name, "Host VGA capture", sizeof(inp->name));1408	inp->type = V4L2_INPUT_TYPE_CAMERA;1409	inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;1410	inp->status = video->v4l2_input_status;1411 1412	return 0;1413}1414 1415static int aspeed_video_get_input(struct file *file, void *fh, unsigned int *i)1416{1417	*i = 0;1418 1419	return 0;1420}1421 1422static int aspeed_video_set_input(struct file *file, void *fh, unsigned int i)1423{1424	if (i)1425		return -EINVAL;1426 1427	return 0;1428}1429 1430static int aspeed_video_get_parm(struct file *file, void *fh,1431				 struct v4l2_streamparm *a)1432{1433	struct aspeed_video *video = video_drvdata(file);1434 1435	a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;1436	a->parm.capture.readbuffers = ASPEED_VIDEO_V4L2_MIN_BUF_REQ;1437	a->parm.capture.timeperframe.numerator = 1;1438	if (!video->frame_rate)1439		a->parm.capture.timeperframe.denominator = MAX_FRAME_RATE;1440	else1441		a->parm.capture.timeperframe.denominator = video->frame_rate;1442 1443	return 0;1444}1445 1446static int aspeed_video_set_parm(struct file *file, void *fh,1447				 struct v4l2_streamparm *a)1448{1449	unsigned int frame_rate = 0;1450	struct aspeed_video *video = video_drvdata(file);1451 1452	a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;1453	a->parm.capture.readbuffers = ASPEED_VIDEO_V4L2_MIN_BUF_REQ;1454 1455	if (a->parm.capture.timeperframe.numerator)1456		frame_rate = a->parm.capture.timeperframe.denominator /1457			a->parm.capture.timeperframe.numerator;1458 1459	if (!frame_rate || frame_rate > MAX_FRAME_RATE) {1460		frame_rate = 0;1461		a->parm.capture.timeperframe.denominator = MAX_FRAME_RATE;1462		a->parm.capture.timeperframe.numerator = 1;1463	}1464 1465	if (video->frame_rate != frame_rate) {1466		video->frame_rate = frame_rate;1467		aspeed_video_update(video, VE_CTRL, VE_CTRL_FRC,1468				    FIELD_PREP(VE_CTRL_FRC, frame_rate));1469	}1470 1471	return 0;1472}1473 1474static int aspeed_video_enum_framesizes(struct file *file, void *fh,1475					struct v4l2_frmsizeenum *fsize)1476{1477	struct aspeed_video *video = video_drvdata(file);1478 1479	if (fsize->index)1480		return -EINVAL;1481 1482	if (fsize->pixel_format != V4L2_PIX_FMT_JPEG)1483		return -EINVAL;1484 1485	fsize->discrete.width = video->pix_fmt.width;1486	fsize->discrete.height = video->pix_fmt.height;1487	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;1488 1489	return 0;1490}1491 1492static int aspeed_video_enum_frameintervals(struct file *file, void *fh,1493					    struct v4l2_frmivalenum *fival)1494{1495	struct aspeed_video *video = video_drvdata(file);1496 1497	if (fival->index)1498		return -EINVAL;1499 1500	if (fival->width != video->detected_timings.width ||1501	    fival->height != video->detected_timings.height)1502		return -EINVAL;1503 1504	if (fival->pixel_format != V4L2_PIX_FMT_JPEG)1505		return -EINVAL;1506 1507	fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;1508 1509	fival->stepwise.min.denominator = MAX_FRAME_RATE;1510	fival->stepwise.min.numerator = 1;1511	fival->stepwise.max.denominator = 1;1512	fival->stepwise.max.numerator = 1;1513	fival->stepwise.step = fival->stepwise.max;1514 1515	return 0;1516}1517 1518static int aspeed_video_set_dv_timings(struct file *file, void *fh,1519				       struct v4l2_dv_timings *timings)1520{1521	struct aspeed_video *video = video_drvdata(file);1522 1523	if (timings->bt.width == video->active_timings.width &&1524	    timings->bt.height == video->active_timings.height)1525		return 0;1526 1527	if (vb2_is_busy(&video->queue))1528		return -EBUSY;1529 1530	video->active_timings = timings->bt;1531 1532	aspeed_video_set_resolution(video);1533 1534	video->pix_fmt.width = timings->bt.width;1535	video->pix_fmt.height = timings->bt.height;1536	video->pix_fmt.sizeimage = video->max_compressed_size;1537 1538	timings->type = V4L2_DV_BT_656_1120;1539 1540	v4l2_dbg(1, debug, &video->v4l2_dev, "set new timings(%dx%d)\n",1541		 timings->bt.width, timings->bt.height);1542 1543	return 0;1544}1545 1546static int aspeed_video_get_dv_timings(struct file *file, void *fh,1547				       struct v4l2_dv_timings *timings)1548{1549	struct aspeed_video *video = video_drvdata(file);1550 1551	timings->type = V4L2_DV_BT_656_1120;1552	timings->bt = video->active_timings;1553 1554	return 0;1555}1556 1557static int aspeed_video_query_dv_timings(struct file *file, void *fh,1558					 struct v4l2_dv_timings *timings)1559{1560	int rc;1561	struct aspeed_video *video = video_drvdata(file);1562 1563	/*1564	 * This blocks only if the driver is currently in the process of1565	 * detecting a new resolution; in the event of no signal or timeout1566	 * this function is woken up.1567	 */1568	if (file->f_flags & O_NONBLOCK) {1569		if (test_bit(VIDEO_RES_CHANGE, &video->flags))1570			return -EAGAIN;1571	} else {1572		rc = wait_event_interruptible(video->wait,1573					      !test_bit(VIDEO_RES_CHANGE,1574							&video->flags));1575		if (rc)1576			return -EINTR;1577	}1578 1579	timings->type = V4L2_DV_BT_656_1120;1580	timings->bt = video->detected_timings;1581 1582	return video->v4l2_input_status ? -ENOLINK : 0;1583}1584 1585static int aspeed_video_enum_dv_timings(struct file *file, void *fh,1586					struct v4l2_enum_dv_timings *timings)1587{1588	return v4l2_enum_dv_timings_cap(timings, &aspeed_video_timings_cap,1589					NULL, NULL);1590}1591 1592static int aspeed_video_dv_timings_cap(struct file *file, void *fh,1593				       struct v4l2_dv_timings_cap *cap)1594{1595	*cap = aspeed_video_timings_cap;1596 1597	return 0;1598}1599 1600static int aspeed_video_sub_event(struct v4l2_fh *fh,1601				  const struct v4l2_event_subscription *sub)1602{1603	switch (sub->type) {1604	case V4L2_EVENT_SOURCE_CHANGE:1605		return v4l2_src_change_event_subscribe(fh, sub);1606	}1607 1608	return v4l2_ctrl_subscribe_event(fh, sub);1609}1610 1611static const struct v4l2_ioctl_ops aspeed_video_ioctl_ops = {1612	.vidioc_querycap = aspeed_video_querycap,1613 1614	.vidioc_enum_fmt_vid_cap = aspeed_video_enum_format,1615	.vidioc_g_fmt_vid_cap = aspeed_video_get_format,1616	.vidioc_s_fmt_vid_cap = aspeed_video_set_format,1617	.vidioc_try_fmt_vid_cap = aspeed_video_get_format,1618 1619	.vidioc_reqbufs = vb2_ioctl_reqbufs,1620	.vidioc_querybuf = vb2_ioctl_querybuf,1621	.vidioc_qbuf = vb2_ioctl_qbuf,1622	.vidioc_expbuf = vb2_ioctl_expbuf,1623	.vidioc_dqbuf = vb2_ioctl_dqbuf,1624	.vidioc_create_bufs = vb2_ioctl_create_bufs,1625	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,1626	.vidioc_streamon = vb2_ioctl_streamon,1627	.vidioc_streamoff = vb2_ioctl_streamoff,1628 1629	.vidioc_enum_input = aspeed_video_enum_input,1630	.vidioc_g_input = aspeed_video_get_input,1631	.vidioc_s_input = aspeed_video_set_input,1632 1633	.vidioc_g_parm = aspeed_video_get_parm,1634	.vidioc_s_parm = aspeed_video_set_parm,1635	.vidioc_enum_framesizes = aspeed_video_enum_framesizes,1636	.vidioc_enum_frameintervals = aspeed_video_enum_frameintervals,1637 1638	.vidioc_s_dv_timings = aspeed_video_set_dv_timings,1639	.vidioc_g_dv_timings = aspeed_video_get_dv_timings,1640	.vidioc_query_dv_timings = aspeed_video_query_dv_timings,1641	.vidioc_enum_dv_timings = aspeed_video_enum_dv_timings,1642	.vidioc_dv_timings_cap = aspeed_video_dv_timings_cap,1643 1644	.vidioc_subscribe_event = aspeed_video_sub_event,1645	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,1646};1647 1648static int aspeed_video_set_ctrl(struct v4l2_ctrl *ctrl)1649{1650	struct aspeed_video *video = container_of(ctrl->handler,1651						  struct aspeed_video,1652						  ctrl_handler);1653 1654	switch (ctrl->id) {1655	case V4L2_CID_JPEG_COMPRESSION_QUALITY:1656		video->jpeg_quality = ctrl->val;1657		if (test_bit(VIDEO_STREAMING, &video->flags))1658			aspeed_video_update_regs(video);1659		break;1660	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:1661		video->yuv420 = (ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_420);1662		if (test_bit(VIDEO_STREAMING, &video->flags))1663			aspeed_video_update_regs(video);1664		break;1665	case V4L2_CID_ASPEED_HQ_MODE:1666		video->hq_mode = ctrl->val;1667		if (test_bit(VIDEO_STREAMING, &video->flags))1668			aspeed_video_update_regs(video);1669		break;1670	case V4L2_CID_ASPEED_HQ_JPEG_QUALITY:1671		video->jpeg_hq_quality = ctrl->val;1672		if (test_bit(VIDEO_STREAMING, &video->flags))1673			aspeed_video_update_regs(video);1674		break;1675	default:1676		return -EINVAL;1677	}1678 1679	return 0;1680}1681 1682static const struct v4l2_ctrl_ops aspeed_video_ctrl_ops = {1683	.s_ctrl = aspeed_video_set_ctrl,1684};1685 1686static const struct v4l2_ctrl_config aspeed_ctrl_HQ_mode = {1687	.ops = &aspeed_video_ctrl_ops,1688	.id = V4L2_CID_ASPEED_HQ_MODE,1689	.name = "Aspeed HQ Mode",1690	.type = V4L2_CTRL_TYPE_BOOLEAN,1691	.min = false,1692	.max = true,1693	.step = 1,1694	.def = false,1695};1696 1697static const struct v4l2_ctrl_config aspeed_ctrl_HQ_jpeg_quality = {1698	.ops = &aspeed_video_ctrl_ops,1699	.id = V4L2_CID_ASPEED_HQ_JPEG_QUALITY,1700	.name = "Aspeed HQ Quality",1701	.type = V4L2_CTRL_TYPE_INTEGER,1702	.min = 1,1703	.max = ASPEED_VIDEO_JPEG_NUM_QUALITIES,1704	.step = 1,1705	.def = 1,1706};1707 1708static void aspeed_video_resolution_work(struct work_struct *work)1709{1710	struct delayed_work *dwork = to_delayed_work(work);1711	struct aspeed_video *video = container_of(dwork, struct aspeed_video,1712						  res_work);1713 1714	aspeed_video_on(video);1715 1716	/* Exit early in case no clients remain */1717	if (test_bit(VIDEO_STOPPED, &video->flags))1718		goto done;1719 1720	aspeed_video_init_regs(video);1721 1722	aspeed_video_update_regs(video);1723 1724	aspeed_video_get_resolution(video);1725 1726	if (video->detected_timings.width != video->active_timings.width ||1727	    video->detected_timings.height != video->active_timings.height) {1728		static const struct v4l2_event ev = {1729			.type = V4L2_EVENT_SOURCE_CHANGE,1730			.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,1731		};1732 1733		v4l2_dbg(1, debug, &video->v4l2_dev, "fire source change event\n");1734		v4l2_event_queue(&video->vdev, &ev);1735	} else if (test_bit(VIDEO_STREAMING, &video->flags)) {1736		/* No resolution change so just restart streaming */1737		aspeed_video_start_frame(video);1738	}1739 1740done:1741	clear_bit(VIDEO_RES_CHANGE, &video->flags);1742	wake_up_interruptible_all(&video->wait);1743}1744 1745static int aspeed_video_open(struct file *file)1746{1747	int rc;1748	struct aspeed_video *video = video_drvdata(file);1749 1750	mutex_lock(&video->video_lock);1751 1752	rc = v4l2_fh_open(file);1753	if (rc) {1754		mutex_unlock(&video->video_lock);1755		return rc;1756	}1757 1758	if (v4l2_fh_is_singular_file(file))1759		aspeed_video_start(video);1760 1761	mutex_unlock(&video->video_lock);1762 1763	return 0;1764}1765 1766static int aspeed_video_release(struct file *file)1767{1768	int rc;1769	struct aspeed_video *video = video_drvdata(file);1770 1771	mutex_lock(&video->video_lock);1772 1773	if (v4l2_fh_is_singular_file(file))1774		aspeed_video_stop(video);1775 1776	rc = _vb2_fop_release(file, NULL);1777 1778	mutex_unlock(&video->video_lock);1779 1780	return rc;1781}1782 1783static const struct v4l2_file_operations aspeed_video_v4l2_fops = {1784	.owner = THIS_MODULE,1785	.read = vb2_fop_read,1786	.poll = vb2_fop_poll,1787	.unlocked_ioctl = video_ioctl2,1788	.mmap = vb2_fop_mmap,1789	.open = aspeed_video_open,1790	.release = aspeed_video_release,1791};1792 1793static int aspeed_video_queue_setup(struct vb2_queue *q,1794				    unsigned int *num_buffers,1795				    unsigned int *num_planes,1796				    unsigned int sizes[],1797				    struct device *alloc_devs[])1798{1799	struct aspeed_video *video = vb2_get_drv_priv(q);1800 1801	if (*num_planes) {1802		if (sizes[0] < video->max_compressed_size)1803			return -EINVAL;1804 1805		return 0;1806	}1807 1808	*num_planes = 1;1809	sizes[0] = video->max_compressed_size;1810 1811	return 0;1812}1813 1814static int aspeed_video_buf_prepare(struct vb2_buffer *vb)1815{1816	struct aspeed_video *video = vb2_get_drv_priv(vb->vb2_queue);1817 1818	if (vb2_plane_size(vb, 0) < video->max_compressed_size)1819		return -EINVAL;1820 1821	return 0;1822}1823 1824static int aspeed_video_start_streaming(struct vb2_queue *q,1825					unsigned int count)1826{1827	int rc;1828	struct aspeed_video *video = vb2_get_drv_priv(q);1829 1830	video->sequence = 0;1831	video->perf.duration_max = 0;1832	video->perf.duration_min = 0xffffffff;1833 1834	aspeed_video_update_regs(video);1835 1836	rc = aspeed_video_start_frame(video);1837	if (rc) {1838		aspeed_video_bufs_done(video, VB2_BUF_STATE_QUEUED);1839		return rc;1840	}1841 1842	set_bit(VIDEO_STREAMING, &video->flags);1843	return 0;1844}1845 1846static void aspeed_video_stop_streaming(struct vb2_queue *q)1847{1848	int rc;1849	struct aspeed_video *video = vb2_get_drv_priv(q);1850 1851	clear_bit(VIDEO_STREAMING, &video->flags);1852 1853	rc = wait_event_timeout(video->wait,1854				!test_bit(VIDEO_FRAME_INPRG, &video->flags),1855				STOP_TIMEOUT);1856	if (!rc) {1857		v4l2_dbg(1, debug, &video->v4l2_dev, "Timed out when stopping streaming\n");1858 1859		/*1860		 * Need to force stop any DMA and try and get HW into a good1861		 * state for future calls to start streaming again.1862		 */1863		aspeed_video_off(video);1864		aspeed_video_on(video);1865 1866		aspeed_video_init_regs(video);1867 1868		aspeed_video_get_resolution(video);1869	}1870 1871	aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);1872}1873 1874static void aspeed_video_buf_queue(struct vb2_buffer *vb)1875{1876	bool empty;1877	struct aspeed_video *video = vb2_get_drv_priv(vb->vb2_queue);1878	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1879	struct aspeed_video_buffer *avb = to_aspeed_video_buffer(vbuf);1880	unsigned long flags;1881 1882	spin_lock_irqsave(&video->lock, flags);1883	empty = list_empty(&video->buffers);1884	list_add_tail(&avb->link, &video->buffers);1885	spin_unlock_irqrestore(&video->lock, flags);1886 1887	if (test_bit(VIDEO_STREAMING, &video->flags) &&1888	    !test_bit(VIDEO_FRAME_INPRG, &video->flags) && empty)1889		aspeed_video_start_frame(video);1890}1891 1892static const struct vb2_ops aspeed_video_vb2_ops = {1893	.queue_setup = aspeed_video_queue_setup,1894	.wait_prepare = vb2_ops_wait_prepare,1895	.wait_finish = vb2_ops_wait_finish,1896	.buf_prepare = aspeed_video_buf_prepare,1897	.start_streaming = aspeed_video_start_streaming,1898	.stop_streaming = aspeed_video_stop_streaming,1899	.buf_queue =  aspeed_video_buf_queue,1900};1901 1902#ifdef CONFIG_DEBUG_FS1903static int aspeed_video_debugfs_show(struct seq_file *s, void *data)1904{1905	struct aspeed_video *v = s->private;1906	u32 val08;1907 1908	seq_puts(s, "\n");1909 1910	seq_puts(s, "Capture:\n");1911	val08 = aspeed_video_read(v, VE_CTRL);1912	if (FIELD_GET(VE_CTRL_DIRECT_FETCH, val08)) {1913		seq_printf(s, "  %-20s:\tDirect fetch\n", "Mode");1914		seq_printf(s, "  %-20s:\t%s\n", "VGA bpp mode",1915			   FIELD_GET(VE_CTRL_INT_DE, val08) ? "16" : "32");1916	} else {1917		seq_printf(s, "  %-20s:\tSync\n", "Mode");1918		seq_printf(s, "  %-20s:\t%s\n", "Video source",1919			   FIELD_GET(VE_CTRL_SOURCE, val08) ?1920			   "external" : "internal");1921		seq_printf(s, "  %-20s:\t%s\n", "DE source",1922			   FIELD_GET(VE_CTRL_INT_DE, val08) ?1923			   "internal" : "external");1924		seq_printf(s, "  %-20s:\t%s\n", "Cursor overlay",1925			   FIELD_GET(VE_CTRL_AUTO_OR_CURSOR, val08) ?1926			   "Without" : "With");1927	}1928 1929	seq_printf(s, "  %-20s:\t%s\n", "Signal",1930		   v->v4l2_input_status ? "Unlock" : "Lock");1931	seq_printf(s, "  %-20s:\t%d\n", "Width", v->pix_fmt.width);1932	seq_printf(s, "  %-20s:\t%d\n", "Height", v->pix_fmt.height);1933	seq_printf(s, "  %-20s:\t%d\n", "FRC", v->frame_rate);1934 1935	seq_puts(s, "\n");1936 1937	seq_puts(s, "Compression:\n");1938	seq_printf(s, "  %-20s:\t%s\n", "Format", format_str[v->format]);1939	seq_printf(s, "  %-20s:\t%s\n", "Subsampling",1940		   v->yuv420 ? "420" : "444");1941	seq_printf(s, "  %-20s:\t%d\n", "Quality", v->jpeg_quality);1942	if (v->format == VIDEO_FMT_ASPEED) {1943		seq_printf(s, "  %-20s:\t%s\n", "HQ Mode",1944			   v->hq_mode ? "on" : "off");1945		seq_printf(s, "  %-20s:\t%d\n", "HQ Quality",1946			   v->hq_mode ? v->jpeg_hq_quality : 0);1947	}1948 1949	seq_puts(s, "\n");1950 1951	seq_puts(s, "Performance:\n");1952	seq_printf(s, "  %-20s:\t%d\n", "Frame#", v->sequence);1953	seq_printf(s, "  %-20s:\n", "Frame Duration(ms)");1954	seq_printf(s, "    %-18s:\t%d\n", "Now", v->perf.duration);1955	seq_printf(s, "    %-18s:\t%d\n", "Min", v->perf.duration_min);1956	seq_printf(s, "    %-18s:\t%d\n", "Max", v->perf.duration_max);1957	seq_printf(s, "  %-20s:\t%d\n", "FPS",1958		   (v->perf.totaltime && v->sequence) ?1959		   1000 / (v->perf.totaltime / v->sequence) : 0);1960 1961	return 0;1962}1963DEFINE_SHOW_ATTRIBUTE(aspeed_video_debugfs);1964 1965static struct dentry *debugfs_entry;1966 1967static void aspeed_video_debugfs_remove(struct aspeed_video *video)1968{1969	debugfs_remove_recursive(debugfs_entry);1970	debugfs_entry = NULL;1971}1972 1973static void aspeed_video_debugfs_create(struct aspeed_video *video)1974{1975	debugfs_entry = debugfs_create_file(DEVICE_NAME, 0444, NULL,1976					    video,1977					    &aspeed_video_debugfs_fops);1978}1979#else1980static void aspeed_video_debugfs_remove(struct aspeed_video *video) { }1981static void aspeed_video_debugfs_create(struct aspeed_video *video) { }1982#endif /* CONFIG_DEBUG_FS */1983 1984static int aspeed_video_setup_video(struct aspeed_video *video)1985{1986	const u64 mask = ~(BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_444) |1987			   BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_420));1988	struct v4l2_device *v4l2_dev = &video->v4l2_dev;1989	struct vb2_queue *vbq = &video->queue;1990	struct video_device *vdev = &video->vdev;1991	struct v4l2_ctrl_handler *hdl = &video->ctrl_handler;1992	int rc;1993 1994	video->pix_fmt.pixelformat = V4L2_PIX_FMT_JPEG;1995	video->pix_fmt.field = V4L2_FIELD_NONE;1996	video->pix_fmt.colorspace = V4L2_COLORSPACE_SRGB;1997	video->pix_fmt.quantization = V4L2_QUANTIZATION_FULL_RANGE;1998	video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;1999 2000	rc = v4l2_device_register(video->dev, v4l2_dev);2001	if (rc) {2002		dev_err(video->dev, "Failed to register v4l2 device\n");2003		return rc;2004	}2005 2006	v4l2_ctrl_handler_init(hdl, 4);2007	v4l2_ctrl_new_std(hdl, &aspeed_video_ctrl_ops,2008			  V4L2_CID_JPEG_COMPRESSION_QUALITY, 0,2009			  ASPEED_VIDEO_JPEG_NUM_QUALITIES - 1, 1, 0);2010	v4l2_ctrl_new_std_menu(hdl, &aspeed_video_ctrl_ops,2011			       V4L2_CID_JPEG_CHROMA_SUBSAMPLING,2012			       V4L2_JPEG_CHROMA_SUBSAMPLING_420, mask,2013			       V4L2_JPEG_CHROMA_SUBSAMPLING_444);2014	v4l2_ctrl_new_custom(hdl, &aspeed_ctrl_HQ_mode, NULL);2015	v4l2_ctrl_new_custom(hdl, &aspeed_ctrl_HQ_jpeg_quality, NULL);2016 2017	rc = hdl->error;2018	if (rc) {2019		v4l2_ctrl_handler_free(&video->ctrl_handler);2020		v4l2_device_unregister(v4l2_dev);2021 2022		dev_err(video->dev, "Failed to init controls: %d\n", rc);2023		return rc;2024	}2025 2026	v4l2_dev->ctrl_handler = hdl;2027 2028	vbq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;2029	vbq->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;2030	vbq->dev = v4l2_dev->dev;2031	vbq->lock = &video->video_lock;2032	vbq->ops = &aspeed_video_vb2_ops;2033	vbq->mem_ops = &vb2_dma_contig_memops;2034	vbq->drv_priv = video;2035	vbq->buf_struct_size = sizeof(struct aspeed_video_buffer);2036	vbq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;2037	vbq->min_queued_buffers = ASPEED_VIDEO_V4L2_MIN_BUF_REQ;2038 2039	rc = vb2_queue_init(vbq);2040	if (rc) {2041		v4l2_ctrl_handler_free(&video->ctrl_handler);2042		v4l2_device_unregister(v4l2_dev);2043 2044		dev_err(video->dev, "Failed to init vb2 queue\n");2045		return rc;2046	}2047 2048	vdev->queue = vbq;2049	vdev->fops = &aspeed_video_v4l2_fops;2050	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |2051		V4L2_CAP_STREAMING;2052	vdev->v4l2_dev = v4l2_dev;2053	strscpy(vdev->name, DEVICE_NAME, sizeof(vdev->name));2054	vdev->vfl_type = VFL_TYPE_VIDEO;2055	vdev->vfl_dir = VFL_DIR_RX;2056	vdev->release = video_device_release_empty;2057	vdev->ioctl_ops = &aspeed_video_ioctl_ops;2058	vdev->lock = &video->video_lock;2059 2060	video_set_drvdata(vdev, video);2061	rc = video_register_device(vdev, VFL_TYPE_VIDEO, 0);2062	if (rc) {2063		v4l2_ctrl_handler_free(&video->ctrl_handler);2064		v4l2_device_unregister(v4l2_dev);2065 2066		dev_err(video->dev, "Failed to register video device\n");2067		return rc;2068	}2069 2070	return 0;2071}2072 2073static int aspeed_video_init(struct aspeed_video *video)2074{2075	int irq;2076	int rc;2077	struct device *dev = video->dev;2078 2079	irq = irq_of_parse_and_map(dev->of_node, 0);2080	if (!irq) {2081		dev_err(dev, "Unable to find IRQ\n");2082		return -ENODEV;2083	}2084 2085	rc = devm_request_threaded_irq(dev, irq, NULL, aspeed_video_irq,2086				       IRQF_ONESHOT, DEVICE_NAME, video);2087	if (rc < 0) {2088		dev_err(dev, "Unable to request IRQ %d\n", irq);2089		return rc;2090	}2091	dev_info(video->dev, "irq %d\n", irq);2092 2093	video->eclk = devm_clk_get(dev, "eclk");2094	if (IS_ERR(video->eclk)) {2095		dev_err(dev, "Unable to get ECLK\n");2096		return PTR_ERR(video->eclk);2097	}2098 2099	rc = clk_prepare(video->eclk);2100	if (rc)2101		return rc;2102 2103	video->vclk = devm_clk_get(dev, "vclk");2104	if (IS_ERR(video->vclk)) {2105		dev_err(dev, "Unable to get VCLK\n");2106		rc = PTR_ERR(video->vclk);2107		goto err_unprepare_eclk;2108	}2109 2110	rc = clk_prepare(video->vclk);2111	if (rc)2112		goto err_unprepare_eclk;2113 2114	of_reserved_mem_device_init(dev);2115 2116	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));2117	if (rc) {2118		dev_err(dev, "Failed to set DMA mask\n");2119		goto err_release_reserved_mem;2120	}2121 2122	if (!aspeed_video_alloc_buf(video, &video->jpeg,2123				    VE_JPEG_HEADER_SIZE)) {2124		dev_err(dev, "Failed to allocate DMA for JPEG header\n");2125		rc = -ENOMEM;2126		goto err_release_reserved_mem;2127	}2128	dev_info(video->dev, "alloc mem size(%d) at %pad for jpeg header\n",2129		 VE_JPEG_HEADER_SIZE, &video->jpeg.dma);2130 2131	aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);2132 2133	return 0;2134 2135err_release_reserved_mem:2136	of_reserved_mem_device_release(dev);2137	clk_unprepare(video->vclk);2138err_unprepare_eclk:2139	clk_unprepare(video->eclk);2140 2141	return rc;2142}2143 2144static const struct of_device_id aspeed_video_of_match[] = {2145	{ .compatible = "aspeed,ast2400-video-engine", .data = &ast2400_config },2146	{ .compatible = "aspeed,ast2500-video-engine", .data = &ast2500_config },2147	{ .compatible = "aspeed,ast2600-video-engine", .data = &ast2600_config },2148	{}2149};2150MODULE_DEVICE_TABLE(of, aspeed_video_of_match);2151 2152static int aspeed_video_probe(struct platform_device *pdev)2153{2154	const struct aspeed_video_config *config;2155	struct aspeed_video *video;2156	int rc;2157 2158	video = devm_kzalloc(&pdev->dev, sizeof(*video), GFP_KERNEL);2159	if (!video)2160		return -ENOMEM;2161 2162	video->base = devm_platform_ioremap_resource(pdev, 0);2163	if (IS_ERR(video->base))2164		return PTR_ERR(video->base);2165 2166	config = of_device_get_match_data(&pdev->dev);2167	if (!config)2168		return -ENODEV;2169 2170	video->jpeg_mode = config->jpeg_mode;2171	video->comp_size_read = config->comp_size_read;2172 2173	video->frame_rate = 30;2174	video->jpeg_hq_quality = 1;2175	video->dev = &pdev->dev;2176	spin_lock_init(&video->lock);2177	mutex_init(&video->video_lock);2178	init_waitqueue_head(&video->wait);2179	INIT_DELAYED_WORK(&video->res_work, aspeed_video_resolution_work);2180	INIT_LIST_HEAD(&video->buffers);2181 2182	rc = aspeed_video_init(video);2183	if (rc)2184		return rc;2185 2186	rc = aspeed_video_setup_video(video);2187	if (rc) {2188		aspeed_video_free_buf(video, &video->jpeg);2189		clk_unprepare(video->vclk);2190		clk_unprepare(video->eclk);2191		return rc;2192	}2193 2194	aspeed_video_debugfs_create(video);2195 2196	return 0;2197}2198 2199static void aspeed_video_remove(struct platform_device *pdev)2200{2201	struct device *dev = &pdev->dev;2202	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);2203	struct aspeed_video *video = to_aspeed_video(v4l2_dev);2204 2205	aspeed_video_off(video);2206 2207	aspeed_video_debugfs_remove(video);2208 2209	clk_unprepare(video->vclk);2210	clk_unprepare(video->eclk);2211 2212	vb2_video_unregister_device(&video->vdev);2213 2214	v4l2_ctrl_handler_free(&video->ctrl_handler);2215 2216	v4l2_device_unregister(v4l2_dev);2217 2218	aspeed_video_free_buf(video, &video->jpeg);2219 2220	of_reserved_mem_device_release(dev);2221}2222 2223static struct platform_driver aspeed_video_driver = {2224	.driver = {2225		.name = DEVICE_NAME,2226		.of_match_table = aspeed_video_of_match,2227	},2228	.probe = aspeed_video_probe,2229	.remove_new = aspeed_video_remove,2230};2231 2232module_platform_driver(aspeed_video_driver);2233 2234module_param(debug, int, 0644);2235MODULE_PARM_DESC(debug, "Debug level (0=off,1=info,2=debug,3=reg ops)");2236 2237MODULE_DESCRIPTION("ASPEED Video Engine Driver");2238MODULE_AUTHOR("Eddie James");2239MODULE_LICENSE("GPL v2");2240