summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/xilinx/xilinx-vip.h
blob: 42fee2026815b78d24886151fbaa914d20cbe7e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
 * Xilinx Video IP Core
 *
 * Copyright (C) 2013-2015 Ideas on Board
 * Copyright (C) 2013-2015 Xilinx, Inc.
 *
 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
 *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef __XILINX_VIP_H__
#define __XILINX_VIP_H__

#include <linux/io.h>
#include <media/v4l2-subdev.h>

struct clk;

/*
 * Minimum and maximum width and height common to most video IP cores. IP
 * cores with different requirements must define their own values.
 */
#define XVIP_MIN_WIDTH			32
#define XVIP_MAX_WIDTH			7680
#define XVIP_MIN_HEIGHT			32
#define XVIP_MAX_HEIGHT			7680

/*
 * Pad IDs. IP cores with with multiple inputs or outputs should define
 * their own values.
 */
#define XVIP_PAD_SINK			0
#define XVIP_PAD_SOURCE			1

/* Xilinx Video IP Control Registers */
#define XVIP_CTRL_CONTROL			0x0000
#define XVIP_CTRL_CONTROL_SW_ENABLE		(1 << 0)
#define XVIP_CTRL_CONTROL_REG_UPDATE		(1 << 1)
#define XVIP_CTRL_CONTROL_BYPASS		(1 << 4)
#define XVIP_CTRL_CONTROL_TEST_PATTERN		(1 << 5)
#define XVIP_CTRL_CONTROL_FRAME_SYNC_RESET	(1 << 30)
#define XVIP_CTRL_CONTROL_SW_RESET		(1 << 31)
#define XVIP_CTRL_STATUS			0x0004
#define XVIP_CTRL_STATUS_PROC_STARTED		(1 << 0)
#define XVIP_CTRL_STATUS_EOF			(1 << 1)
#define XVIP_CTRL_ERROR				0x0008
#define XVIP_CTRL_ERROR_SLAVE_EOL_EARLY		(1 << 0)
#define XVIP_CTRL_ERROR_SLAVE_EOL_LATE		(1 << 1)
#define XVIP_CTRL_ERROR_SLAVE_SOF_EARLY		(1 << 2)
#define XVIP_CTRL_ERROR_SLAVE_SOF_LATE		(1 << 3)
#define XVIP_CTRL_IRQ_ENABLE			0x000c
#define XVIP_CTRL_IRQ_ENABLE_PROC_STARTED	(1 << 0)
#define XVIP_CTRL_IRQ_EOF			(1 << 1)
#define XVIP_CTRL_VERSION			0x0010
#define XVIP_CTRL_VERSION_MAJOR_MASK		(0xff << 24)
#define XVIP_CTRL_VERSION_MAJOR_SHIFT		24
#define XVIP_CTRL_VERSION_MINOR_MASK		(0xff << 16)
#define XVIP_CTRL_VERSION_MINOR_SHIFT		16
#define XVIP_CTRL_VERSION_REVISION_MASK		(0xf << 12)
#define XVIP_CTRL_VERSION_REVISION_SHIFT	12
#define XVIP_CTRL_VERSION_PATCH_MASK		(0xf << 8)
#define XVIP_CTRL_VERSION_PATCH_SHIFT		8
#define XVIP_CTRL_VERSION_INTERNAL_MASK		(0xff << 0)
#define XVIP_CTRL_VERSION_INTERNAL_SHIFT	0

/* Xilinx Video IP Timing Registers */
#define XVIP_ACTIVE_SIZE			0x0020
#define XVIP_ACTIVE_VSIZE_MASK			(0x7ff << 16)
#define XVIP_ACTIVE_VSIZE_SHIFT			16
#define XVIP_ACTIVE_HSIZE_MASK			(0x7ff << 0)
#define XVIP_ACTIVE_HSIZE_SHIFT			0
#define XVIP_ENCODING				0x0028
#define XVIP_ENCODING_NBITS_8			(0 << 4)
#define XVIP_ENCODING_NBITS_10			(1 << 4)
#define XVIP_ENCODING_NBITS_12			(2 << 4)
#define XVIP_ENCODING_NBITS_16			(3 << 4)
#define XVIP_ENCODING_NBITS_MASK		(3 << 4)
#define XVIP_ENCODING_NBITS_SHIFT		4
#define XVIP_ENCODING_VIDEO_FORMAT_YUV422	(0 << 0)
#define XVIP_ENCODING_VIDEO_FORMAT_YUV444	(1 << 0)
#define XVIP_ENCODING_VIDEO_FORMAT_RGB		(2 << 0)
#define XVIP_ENCODING_VIDEO_FORMAT_YUV420	(3 << 0)
#define XVIP_ENCODING_VIDEO_FORMAT_MASK		(3 << 0)
#define XVIP_ENCODING_VIDEO_FORMAT_SHIFT	0

/**
 * struct xvip_device - Xilinx Video IP device structure
 * @subdev: V4L2 subdevice
 * @dev: (OF) device
 * @iomem: device I/O register space remapped to kernel virtual memory
 * @clk: video core clock
 * @saved_ctrl: saved control register for resume / suspend
 */
struct xvip_device {
	struct v4l2_subdev subdev;
	struct device *dev;
	void __iomem *iomem;
	struct clk *clk;
	u32 saved_ctrl;
};

/**
 * struct xvip_video_format - Xilinx Video IP video format description
 * @vf_code: AXI4 video format code
 * @width: AXI4 format width in bits per component
 * @pattern: CFA pattern for Mono/Sensor formats
 * @code: media bus format code
 * @bpp: bytes per pixel (when stored in memory)
 * @fourcc: V4L2 pixel format FCC identifier
 * @description: format description, suitable for userspace
 */
struct xvip_video_format {
	unsigned int vf_code;
	unsigned int width;
	const char *pattern;
	unsigned int code;
	unsigned int bpp;
	u32 fourcc;
	const char *description;
};

const struct xvip_video_format *xvip_get_format_by_code(unsigned int code);
const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc);
const struct xvip_video_format *xvip_of_get_format(struct device_node *node);
void xvip_set_format_size(struct v4l2_mbus_framefmt *format,
			  const struct v4l2_subdev_format *fmt);
int xvip_enum_mbus_code(struct v4l2_subdev *subdev,
			struct v4l2_subdev_pad_config *cfg,
			struct v4l2_subdev_mbus_code_enum *code);
int xvip_enum_frame_size(struct v4l2_subdev *subdev,
			 struct v4l2_subdev_pad_config *cfg,
			 struct v4l2_subdev_frame_size_enum *fse);

static inline u32 xvip_read(struct xvip_device *xvip, u32 addr)
{
	return ioread32(xvip->iomem + addr);
}

static inline void xvip_write(struct xvip_device *xvip, u32 addr, u32 value)
{
	iowrite32(value, xvip->iomem + addr);
}

static inline void xvip_clr(struct xvip_device *xvip, u32 addr, u32 clr)
{
	xvip_write(xvip, addr, xvip_read(xvip, addr) & ~clr);
}

static inline void xvip_set(struct xvip_device *xvip, u32 addr, u32 set)
{
	xvip_write(xvip, addr, xvip_read(xvip, addr) | set);
}

void xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set);
void xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set);

int xvip_init_resources(struct xvip_device *xvip);
void xvip_cleanup_resources(struct xvip_device *xvip);

static inline void xvip_reset(struct xvip_device *xvip)
{
	xvip_write(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_SW_RESET);
}

static inline void xvip_start(struct xvip_device *xvip)
{
	xvip_set(xvip, XVIP_CTRL_CONTROL,
		 XVIP_CTRL_CONTROL_SW_ENABLE | XVIP_CTRL_CONTROL_REG_UPDATE);
}

static inline void xvip_stop(struct xvip_device *xvip)
{
	xvip_clr(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_SW_ENABLE);
}

static inline void xvip_resume(struct xvip_device *xvip)
{
	xvip_write(xvip, XVIP_CTRL_CONTROL,
		   xvip->saved_ctrl | XVIP_CTRL_CONTROL_SW_ENABLE);
}

static inline void xvip_suspend(struct xvip_device *xvip)
{
	xvip->saved_ctrl = xvip_read(xvip, XVIP_CTRL_CONTROL);
	xvip_write(xvip, XVIP_CTRL_CONTROL,
		   xvip->saved_ctrl & ~XVIP_CTRL_CONTROL_SW_ENABLE);
}

static inline void xvip_set_frame_size(struct xvip_device *xvip,
				       const struct v4l2_mbus_framefmt *format)
{
	xvip_write(xvip, XVIP_ACTIVE_SIZE,
		   (format->height << XVIP_ACTIVE_VSIZE_SHIFT) |
		   (format->width << XVIP_ACTIVE_HSIZE_SHIFT));
}

static inline void xvip_get_frame_size(struct xvip_device *xvip,
				       struct v4l2_mbus_framefmt *format)
{
	u32 reg;

	reg = xvip_read(xvip, XVIP_ACTIVE_SIZE);
	format->width = (reg & XVIP_ACTIVE_HSIZE_MASK) >>
			XVIP_ACTIVE_HSIZE_SHIFT;
	format->height = (reg & XVIP_ACTIVE_VSIZE_MASK) >>
			 XVIP_ACTIVE_VSIZE_SHIFT;
}

static inline void xvip_enable_reg_update(struct xvip_device *xvip)
{
	xvip_set(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_REG_UPDATE);
}

static inline void xvip_disable_reg_update(struct xvip_device *xvip)
{
	xvip_clr(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_REG_UPDATE);
}

static inline void xvip_print_version(struct xvip_device *xvip)
{
	u32 version;

	version = xvip_read(xvip, XVIP_CTRL_VERSION);

	dev_info(xvip->dev, "device found, version %u.%02x%x\n",
		 ((version & XVIP_CTRL_VERSION_MAJOR_MASK) >>
		  XVIP_CTRL_VERSION_MAJOR_SHIFT),
		 ((version & XVIP_CTRL_VERSION_MINOR_MASK) >>
		  XVIP_CTRL_VERSION_MINOR_SHIFT),
		 ((version & XVIP_CTRL_VERSION_REVISION_MASK) >>
		  XVIP_CTRL_VERSION_REVISION_SHIFT));
}

#endif /* __XILINX_VIP_H__ */