summaryrefslogtreecommitdiff
path: root/drivers/media/platform/rockchip/rkcif/rkcif-common.h
blob: dd92cfbc879f01fec0983cc722c86c8da239a987 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Rockchip Camera Interface (CIF) Driver
 *
 * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
 * Copyright (C) 2023 Mehdi Djait <mehdi.djait@bootlin.com>
 * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
 * Copyright (C) 2025 Collabora, Ltd.
 */

#ifndef _RKCIF_COMMON_H
#define _RKCIF_COMMON_H

#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/regmap.h>

#include <media/media-device.h>
#include <media/media-entity.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mc.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf2-v4l2.h>

#include "rkcif-regs.h"

#define RKCIF_DRIVER_NAME "rockchip-cif"
#define RKCIF_CLK_MAX	  4

enum rkcif_format_type {
	RKCIF_FMT_TYPE_INVALID,
	RKCIF_FMT_TYPE_YUV,
	RKCIF_FMT_TYPE_RAW,
};

enum rkcif_id_index {
	RKCIF_ID0,
	RKCIF_ID1,
	RKCIF_ID2,
	RKCIF_ID3,
	RKCIF_ID_MAX
};

enum rkcif_interface_index {
	RKCIF_DVP,
	RKCIF_MIPI_BASE,
	RKCIF_MIPI1 = RKCIF_MIPI_BASE,
	RKCIF_MIPI2,
	RKCIF_MIPI3,
	RKCIF_MIPI4,
	RKCIF_MIPI5,
	RKCIF_MIPI6,
	RKCIF_MIPI_MAX,
	RKCIF_IF_MAX = RKCIF_MIPI_MAX
};

enum rkcif_interface_pad_index {
	RKCIF_IF_PAD_SINK,
	RKCIF_IF_PAD_SRC,
	RKCIF_IF_PAD_MAX
};

enum rkcif_interface_status {
	RKCIF_IF_INACTIVE,
	RKCIF_IF_ACTIVE,
};

enum rkcif_interface_type {
	RKCIF_IF_INVALID,
	RKCIF_IF_DVP,
	RKCIF_IF_MIPI,
};

enum rkcif_mipi_format_type {
	RKCIF_MIPI_TYPE_INVALID,
	RKCIF_MIPI_TYPE_RAW8,
	RKCIF_MIPI_TYPE_RAW10,
	RKCIF_MIPI_TYPE_RAW12,
	RKCIF_MIPI_TYPE_RGB888,
	RKCIF_MIPI_TYPE_YUV422SP,
	RKCIF_MIPI_TYPE_YUV420SP,
	RKCIF_MIPI_TYPE_YUV400,
};

struct rkcif_buffer {
	struct vb2_v4l2_buffer vb;
	struct list_head queue;
	dma_addr_t buff_addr[VIDEO_MAX_PLANES];
	bool is_dummy;
};

struct rkcif_dummy_buffer {
	struct rkcif_buffer buffer;
	void *vaddr;
	u32 size;
};

enum rkcif_plane_index {
	RKCIF_PLANE_Y,
	RKCIF_PLANE_UV,
	RKCIF_PLANE_MAX
};

struct rkcif_input_fmt {
	u32 mbus_code;

	enum rkcif_format_type fmt_type;
	enum v4l2_field field;

	union {
		u32 dvp_fmt_val;
	};
};

struct rkcif_output_fmt {
	u32 fourcc;
	u32 mbus_code;
	u8 cplanes;
	u8 depth;

	union {
		u32 dvp_fmt_val;
		struct {
			u8 dt;
			bool compact;
			enum rkcif_mipi_format_type type;
		} mipi;
	};
};

struct rkcif_interface;

struct rkcif_remote {
	struct v4l2_async_connection async_conn;
	struct v4l2_subdev *sd;

	struct rkcif_interface *interface;
};

struct rkcif_stream {
	enum rkcif_id_index id;
	struct rkcif_device *rkcif;
	struct rkcif_interface *interface;
	const struct rkcif_output_fmt *out_fmts;
	unsigned int out_fmts_num;

	/* in ping-pong mode, two buffers can be provided to the HW */
	struct rkcif_buffer *buffers[2];
	int frame_idx;
	int frame_phase;

	/* in case of no available buffer, HW can write to the dummy buffer */
	struct rkcif_dummy_buffer dummy;

	bool stopping;
	wait_queue_head_t wq_stopped;

	/* queue of available buffers plus spinlock that protects it */
	spinlock_t driver_queue_lock;
	struct list_head driver_queue;

	/* lock used by the V4L2 core */
	struct mutex vlock;

	struct media_pad pad;
	struct media_pipeline pipeline;
	struct v4l2_pix_format_mplane pix;
	struct vb2_queue buf_queue;
	struct video_device vdev;

	void (*queue_buffer)(struct rkcif_stream *stream, unsigned int index);
	int (*start_streaming)(struct rkcif_stream *stream);
	void (*stop_streaming)(struct rkcif_stream *stream);
};

struct rkcif_dvp {
	u32 dvp_clk_delay;
};

struct rkcif_interface {
	enum rkcif_interface_type type;
	enum rkcif_interface_status status;
	enum rkcif_interface_index index;
	struct rkcif_device *rkcif;
	struct rkcif_remote *remote;
	struct rkcif_stream streams[RKCIF_ID_MAX];
	unsigned int streams_num;
	const struct rkcif_input_fmt *in_fmts;
	unsigned int in_fmts_num;

	struct media_pad pads[RKCIF_IF_PAD_MAX];
	struct v4l2_fwnode_endpoint vep;
	struct v4l2_subdev sd;

	union {
		struct rkcif_dvp dvp;
	};

	void (*set_crop)(struct rkcif_stream *stream, u16 left, u16 top);
};

struct rkcif_mipi_match_data {
	unsigned int mipi_num;
	unsigned int regs[RKCIF_MIPI_REGISTER_MAX];
	unsigned int regs_id[RKCIF_ID_MAX][RKCIF_MIPI_ID_REGISTER_MAX];
	u32 (*mipi_ctrl0)(struct rkcif_stream *stream,
			  const struct rkcif_output_fmt *active_out_fmt);
	struct {
		unsigned int offset;
	} blocks[RKCIF_MIPI_MAX - RKCIF_MIPI_BASE];
};

struct rkcif_dvp_match_data {
	const struct rkcif_input_fmt *in_fmts;
	unsigned int in_fmts_num;
	const struct rkcif_output_fmt *out_fmts;
	unsigned int out_fmts_num;
	void (*setup)(struct rkcif_device *rkcif);
	bool has_scaler;
	bool has_ids;
	unsigned int regs[RKCIF_DVP_REGISTER_MAX];
};

struct rkcif_match_data {
	const char *const *clks;
	unsigned int clks_num;
	const struct rkcif_dvp_match_data *dvp;
	const struct rkcif_mipi_match_data *mipi;
};

struct rkcif_device {
	struct device *dev;

	const struct rkcif_match_data *match_data;
	struct clk_bulk_data clks[RKCIF_CLK_MAX];
	unsigned int clks_num;
	struct regmap *grf;
	struct reset_control *reset;
	void __iomem *base_addr;

	struct rkcif_interface interfaces[RKCIF_IF_MAX];

	struct media_device media_dev;
	struct v4l2_device v4l2_dev;
	struct v4l2_async_notifier notifier;
};

#endif