• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip CIF Driver
4  *
5  * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
6  */
7 #include <linux/clk.h>
8 #include <linux/delay.h>
9 #include <linux/interrupt.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/of_gpio.h>
13 #include <linux/of_graph.h>
14 #include <linux/of_platform.h>
15 #include <linux/of_reserved_mem.h>
16 #include <linux/reset.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/pinctrl/consumer.h>
19 #include <linux/regmap.h>
20 #include <media/videobuf2-dma-contig.h>
21 #include <media/v4l2-fwnode.h>
22 #include "dev.h"
23 #include <linux/regulator/consumer.h>
24 #include <linux/rk-camera-module.h>
25 
to_sditf_priv(struct v4l2_subdev * subdev)26 static inline struct sditf_priv *to_sditf_priv(struct v4l2_subdev *subdev)
27 {
28 	return container_of(subdev, struct sditf_priv, sd);
29 }
30 
sditf_get_hdr_mode(struct sditf_priv * priv)31 static void sditf_get_hdr_mode(struct sditf_priv *priv)
32 {
33 	struct rkcif_device *cif_dev = priv->cif_dev;
34 	struct rkmodule_hdr_cfg hdr_cfg;
35 	int ret = 0;
36 
37 	if (!cif_dev->terminal_sensor.sd)
38 		rkcif_update_sensor_info(&cif_dev->stream[0]);
39 
40 	if (cif_dev->terminal_sensor.sd) {
41 		ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
42 				       core, ioctl,
43 				       RKMODULE_GET_HDR_CFG,
44 				       &hdr_cfg);
45 		if (!ret)
46 			priv->hdr_cfg = hdr_cfg;
47 		else
48 			priv->hdr_cfg.hdr_mode = NO_HDR;
49 	} else {
50 		priv->hdr_cfg.hdr_mode = NO_HDR;
51 	}
52 }
53 
sditf_g_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_frame_interval * fi)54 static int sditf_g_frame_interval(struct v4l2_subdev *sd,
55 				  struct v4l2_subdev_frame_interval *fi)
56 {
57 	struct sditf_priv *priv = to_sditf_priv(sd);
58 	struct rkcif_device *cif_dev = priv->cif_dev;
59 	struct v4l2_subdev *sensor_sd;
60 
61 	if (!cif_dev->terminal_sensor.sd)
62 		rkcif_update_sensor_info(&cif_dev->stream[0]);
63 
64 	if (cif_dev->terminal_sensor.sd) {
65 		sensor_sd = cif_dev->terminal_sensor.sd;
66 		return v4l2_subdev_call(sensor_sd, video, g_frame_interval, fi);
67 	}
68 
69 	return -EINVAL;
70 }
71 
sditf_g_mbus_config(struct v4l2_subdev * sd,unsigned int pad_id,struct v4l2_mbus_config * config)72 static int sditf_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
73 			       struct v4l2_mbus_config *config)
74 {
75 	struct sditf_priv *priv = to_sditf_priv(sd);
76 	struct rkcif_device *cif_dev = priv->cif_dev;
77 	struct v4l2_subdev *sensor_sd;
78 
79 	if (!cif_dev->active_sensor)
80 		rkcif_update_sensor_info(&cif_dev->stream[0]);
81 
82 	if (cif_dev->active_sensor) {
83 		sensor_sd = cif_dev->active_sensor->sd;
84 		return v4l2_subdev_call(sensor_sd, pad, get_mbus_config, 0, config);
85 	}
86 
87 	return -EINVAL;
88 }
89 
sditf_get_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)90 static int sditf_get_set_fmt(struct v4l2_subdev *sd,
91 			     struct v4l2_subdev_pad_config *cfg,
92 			     struct v4l2_subdev_format *fmt)
93 {
94 	struct sditf_priv *priv = to_sditf_priv(sd);
95 	struct rkcif_device *cif_dev = priv->cif_dev;
96 	struct v4l2_subdev_selection input_sel;
97 	struct v4l2_pix_format_mplane pixm;
98 	int ret = -EINVAL;
99 
100 	if (!cif_dev->terminal_sensor.sd)
101 		rkcif_update_sensor_info(&cif_dev->stream[0]);
102 
103 	if (cif_dev->terminal_sensor.sd) {
104 		sditf_get_hdr_mode(priv);
105 		fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
106 		fmt->pad = 0;
107 		ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd, pad, get_fmt, NULL, fmt);
108 		if (ret) {
109 			v4l2_err(&priv->sd,
110 				 "%s: get sensor format failed\n", __func__);
111 			return ret;
112 		}
113 
114 		input_sel.target = V4L2_SEL_TGT_CROP_BOUNDS;
115 		input_sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
116 		input_sel.pad = 0;
117 		ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
118 				       pad, get_selection, NULL,
119 				       &input_sel);
120 		if (!ret) {
121 			fmt->format.width = input_sel.r.width;
122 			fmt->format.height = input_sel.r.height;
123 		}
124 		priv->cap_info.width = fmt->format.width;
125 		priv->cap_info.height = fmt->format.height;
126 		pixm.pixelformat = rkcif_mbus_pixelcode_to_v4l2(fmt->format.code);
127 		pixm.width = priv->cap_info.width;
128 		pixm.height = priv->cap_info.height;
129 		v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
130 			"%s, width %d, height %d, hdr mode %d\n",
131 			__func__, fmt->format.width, fmt->format.width, priv->hdr_cfg.hdr_mode);
132 		if (priv->hdr_cfg.hdr_mode == NO_HDR) {
133 			rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
134 		} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
135 			rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
136 			rkcif_set_fmt(&cif_dev->stream[1], &pixm, false);
137 		} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
138 			rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
139 			rkcif_set_fmt(&cif_dev->stream[1], &pixm, false);
140 			rkcif_set_fmt(&cif_dev->stream[2], &pixm, false);
141 		}
142 	}
143 
144 	return 0;
145 }
146 
sditf_init_buf(struct sditf_priv * priv)147 static int sditf_init_buf(struct sditf_priv *priv)
148 {
149 	struct rkcif_device *cif_dev = priv->cif_dev;
150 	int ret = 0;
151 
152 	if (priv->hdr_cfg.hdr_mode == HDR_X2) {
153 		ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
154 	} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
155 		ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
156 		ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num);
157 	} else {
158 		ret = -EINVAL;
159 	}
160 	return ret;
161 }
162 
sditf_free_buf(struct sditf_priv * priv)163 static void sditf_free_buf(struct sditf_priv *priv)
164 {
165 	struct rkcif_device *cif_dev = priv->cif_dev;
166 
167 	if (priv->hdr_cfg.hdr_mode == HDR_X2) {
168 		rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
169 	} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
170 		rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
171 		rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num);
172 	}
173 }
174 
sditf_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)175 static int sditf_get_selection(struct v4l2_subdev *sd,
176 			       struct v4l2_subdev_pad_config *cfg,
177 			       struct v4l2_subdev_selection *sel)
178 {
179 	return -EINVAL;
180 }
181 
sditf_reinit_mode(struct sditf_priv * priv,struct rkisp_vicap_mode * mode)182 static void sditf_reinit_mode(struct sditf_priv *priv, struct rkisp_vicap_mode *mode)
183 {
184 	if (mode->is_rdbk) {
185 		priv->toisp_inf.link_mode = TOISP_NONE;
186 	} else {
187 		if (strstr(mode->name, RKISP0_DEVNAME))
188 			priv->toisp_inf.link_mode = TOISP0;
189 		else if (strstr(mode->name, RKISP1_DEVNAME))
190 			priv->toisp_inf.link_mode = TOISP1;
191 		else if (strstr(mode->name, RKISP_UNITE_DEVNAME))
192 			priv->toisp_inf.link_mode = TOISP_UNITE;
193 		else
194 			v4l2_err(&priv->cif_dev->v4l2_dev,
195 				 "%s, mode name err, mode name: %s\n",
196 				 __func__, mode->name);
197 	}
198 	v4l2_dbg(3, rkcif_debug, &priv->cif_dev->v4l2_dev,
199 		 "%s, mode->is_rdbk %d, mode->name %s, link_mode %d\n",
200 		 __func__, mode->is_rdbk, mode->name, priv->toisp_inf.link_mode);
201 }
202 
sditf_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)203 static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
204 {
205 	struct sditf_priv *priv = to_sditf_priv(sd);
206 	struct rkisp_vicap_mode *mode;
207 	struct v4l2_subdev_format fmt;
208 	struct rkcif_device *cif_dev = priv->cif_dev;
209 	struct v4l2_subdev *sensor_sd;
210 	int *pbuf_num = NULL;
211 	int ret = 0;
212 
213 	switch (cmd) {
214 	case RKISP_VICAP_CMD_MODE:
215 		mode = (struct rkisp_vicap_mode *)arg;
216 		memcpy(&priv->mode, mode, sizeof(*mode));
217 		sditf_reinit_mode(priv, &priv->mode);
218 		return 0;
219 	case RKISP_VICAP_CMD_INIT_BUF:
220 		pbuf_num = (int *)arg;
221 		priv->buf_num = *pbuf_num;
222 		sditf_get_set_fmt(&priv->sd, NULL, &fmt);
223 		ret = sditf_init_buf(priv);
224 		return ret;
225 	case RKMODULE_GET_HDR_CFG:
226 		if (!cif_dev->terminal_sensor.sd)
227 			rkcif_update_sensor_info(&cif_dev->stream[0]);
228 
229 		if (cif_dev->terminal_sensor.sd) {
230 			sensor_sd = cif_dev->terminal_sensor.sd;
231 			return v4l2_subdev_call(sensor_sd, core, ioctl, cmd, arg);
232 		}
233 		break;
234 	default:
235 		break;
236 	}
237 
238 	return -EINVAL;
239 }
240 
241 #ifdef CONFIG_COMPAT
sditf_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)242 static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
243 				  unsigned int cmd, unsigned long arg)
244 {
245 	void __user *up = compat_ptr(arg);
246 	struct sditf_priv *priv = to_sditf_priv(sd);
247 	struct rkcif_device *cif_dev = priv->cif_dev;
248 	struct v4l2_subdev *sensor_sd;
249 	struct rkisp_vicap_mode *mode;
250 	int buf_num;
251 	int ret = 0;
252 
253 	switch (cmd) {
254 	case RKISP_VICAP_CMD_MODE:
255 		mode = kzalloc(sizeof(*mode), GFP_KERNEL);
256 		if (!mode) {
257 			ret = -ENOMEM;
258 			return ret;
259 		}
260 		if (copy_from_user(mode, up, sizeof(*mode))) {
261 			kfree(mode);
262 			return -EFAULT;
263 		}
264 		ret = sditf_ioctl(sd, cmd, mode);
265 		kfree(mode);
266 		return ret;
267 	case RKISP_VICAP_CMD_INIT_BUF:
268 		if (copy_from_user(&buf_num, up, sizeof(int)))
269 			return -EFAULT;
270 		ret = sditf_ioctl(sd, cmd, &buf_num);
271 		return ret;
272 	default:
273 		break;
274 	}
275 
276 	if (!cif_dev->terminal_sensor.sd)
277 		rkcif_update_sensor_info(&cif_dev->stream[0]);
278 
279 	if (cif_dev->terminal_sensor.sd) {
280 		sensor_sd = cif_dev->terminal_sensor.sd;
281 		return v4l2_subdev_call(sensor_sd, core, compat_ioctl32, cmd, arg);
282 	}
283 
284 	return -EINVAL;
285 }
286 #endif
287 
sditf_channel_enable(struct sditf_priv * priv,int user)288 static int sditf_channel_enable(struct sditf_priv *priv, int user)
289 {
290 	struct rkcif_device *cif_dev = priv->cif_dev;
291 	unsigned int ch0 = 0, ch1 = 0, ch2 = 0;
292 	unsigned int ctrl_val = 0;
293 	unsigned int int_en = 0;
294 	unsigned int offset_x = 0;
295 	unsigned int offset_y = 0;
296 	unsigned int width = priv->cap_info.width;
297 	unsigned int height = priv->cap_info.height;
298 
299 	if (priv->hdr_cfg.hdr_mode == NO_HDR) {
300 		if (cif_dev->inf_id == RKCIF_MIPI_LVDS)
301 			ch0 = cif_dev->csi_host_idx * 4;
302 		else
303 			ch0 = 24;//dvp
304 		ctrl_val = (ch0 << 3) | 0x1;
305 		if (user == 0)
306 			int_en = 0x04104003;
307 		else
308 			int_en = 0x08820003;
309 		priv->toisp_inf.ch_info[0].is_valid = true;
310 		priv->toisp_inf.ch_info[0].id = ch0;
311 	} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
312 		ch0 = cif_dev->csi_host_idx * 4 + 1;
313 		ch1 = cif_dev->csi_host_idx * 4;
314 		ctrl_val = (ch0 << 3) | 0x1;
315 		ctrl_val |= (ch1 << 11) | 0x100;
316 		if (user == 0)
317 			int_en = 0x0430c003;
318 		else
319 			int_en = 0x09860003;
320 		priv->toisp_inf.ch_info[0].is_valid = true;
321 		priv->toisp_inf.ch_info[0].id = ch0;
322 		priv->toisp_inf.ch_info[1].is_valid = true;
323 		priv->toisp_inf.ch_info[1].id = ch1;
324 	} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
325 		ch0 = cif_dev->csi_host_idx * 4 + 2;
326 		ch1 = cif_dev->csi_host_idx * 4 + 1;
327 		ch2 = cif_dev->csi_host_idx * 4;
328 		ctrl_val = (ch0 << 3) | 0x1;
329 		ctrl_val |= (ch1 << 11) | 0x100;
330 		ctrl_val |= (ch2 << 19) | 0x10000;
331 		if (user == 0)
332 			int_en = 0x0471c003;
333 		else
334 			int_en = 0x0b8e0003;
335 		priv->toisp_inf.ch_info[0].is_valid = true;
336 		priv->toisp_inf.ch_info[0].id = ch0;
337 		priv->toisp_inf.ch_info[1].is_valid = true;
338 		priv->toisp_inf.ch_info[1].id = ch1;
339 		priv->toisp_inf.ch_info[2].is_valid = true;
340 		priv->toisp_inf.ch_info[2].id = ch2;
341 	}
342 	if (user == 0) {
343 		if (priv->toisp_inf.link_mode == TOISP_UNITE)
344 			width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
345 		rkcif_write_register_or(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_val);
346 		if (width && height) {
347 			rkcif_write_register(cif_dev, CIF_REG_TOISP0_CROP,
348 				offset_x | (offset_y << 16));
349 			rkcif_write_register(cif_dev, CIF_REG_TOISP0_SIZE,
350 				width | (height << 16));
351 		} else {
352 			return -EINVAL;
353 		}
354 		rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, int_en);
355 	} else {
356 		if (priv->toisp_inf.link_mode == TOISP_UNITE) {
357 			offset_x = priv->cap_info.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL;
358 			width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
359 		}
360 		rkcif_write_register_or(cif_dev, CIF_REG_TOISP1_CTRL, ctrl_val);
361 		if (width && height) {
362 			rkcif_write_register(cif_dev, CIF_REG_TOISP1_CROP,
363 				offset_x | (offset_y << 16));
364 			rkcif_write_register(cif_dev, CIF_REG_TOISP1_SIZE,
365 				width | (height << 16));
366 		} else {
367 			return -EINVAL;
368 		}
369 		rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, int_en);
370 	}
371 	return 0;
372 }
373 
sditf_channel_disable(struct sditf_priv * priv,int user)374 static __maybe_unused void sditf_channel_disable(struct sditf_priv *priv, int user)
375 {
376 	struct rkcif_device *cif_dev = priv->cif_dev;
377 	unsigned int ctrl_val = 0;
378 
379 	if (priv->hdr_cfg.hdr_mode == NO_HDR)
380 		ctrl_val = 0x01;
381 	else if (priv->hdr_cfg.hdr_mode == HDR_X2)
382 		ctrl_val = 0x101;
383 	else if (priv->hdr_cfg.hdr_mode == HDR_X3)
384 		ctrl_val = 0x10101;
385 	if (user == 0)
386 		rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val);
387 	else
388 		rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val);
389 	priv->toisp_inf.ch_info[0].is_valid = false;
390 	priv->toisp_inf.ch_info[1].is_valid = false;
391 	priv->toisp_inf.ch_info[2].is_valid = false;
392 }
393 
sditf_start_stream(struct sditf_priv * priv)394 static int sditf_start_stream(struct sditf_priv *priv)
395 {
396 	struct rkcif_device *cif_dev = priv->cif_dev;
397 	struct v4l2_subdev_format fmt;
398 
399 	sditf_get_set_fmt(&priv->sd, NULL, &fmt);
400 	if (priv->toisp_inf.link_mode == TOISP0) {
401 		sditf_channel_enable(priv, 0);
402 	} else if (priv->toisp_inf.link_mode == TOISP1) {
403 		sditf_channel_enable(priv, 1);
404 	} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
405 		sditf_channel_enable(priv, 0);
406 		sditf_channel_enable(priv, 1);
407 	}
408 
409 	if (priv->hdr_cfg.hdr_mode == NO_HDR) {
410 		rkcif_do_start_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
411 	} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
412 		rkcif_do_start_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
413 		rkcif_do_start_stream(&cif_dev->stream[1], RKCIF_STREAM_MODE_TOISP);
414 	} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
415 		rkcif_do_start_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
416 		rkcif_do_start_stream(&cif_dev->stream[1], RKCIF_STREAM_MODE_TOISP);
417 		rkcif_do_start_stream(&cif_dev->stream[2], RKCIF_STREAM_MODE_TOISP);
418 	}
419 	return 0;
420 }
421 
sditf_stop_stream(struct sditf_priv * priv)422 static int sditf_stop_stream(struct sditf_priv *priv)
423 {
424 	struct rkcif_device *cif_dev = priv->cif_dev;
425 
426 	if (priv->hdr_cfg.hdr_mode == NO_HDR) {
427 		rkcif_do_stop_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
428 	} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
429 		rkcif_do_stop_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
430 		rkcif_do_stop_stream(&cif_dev->stream[1], RKCIF_STREAM_MODE_TOISP);
431 	} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
432 		rkcif_do_stop_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
433 		rkcif_do_stop_stream(&cif_dev->stream[1], RKCIF_STREAM_MODE_TOISP);
434 		rkcif_do_stop_stream(&cif_dev->stream[2], RKCIF_STREAM_MODE_TOISP);
435 	}
436 	return 0;
437 }
438 
sditf_s_stream(struct v4l2_subdev * sd,int on)439 static int sditf_s_stream(struct v4l2_subdev *sd, int on)
440 {
441 	struct sditf_priv *priv = to_sditf_priv(sd);
442 	struct rkcif_device *cif_dev = priv->cif_dev;
443 	int ret = 0;
444 
445 	if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
446 		if (priv->toisp_inf.link_mode == TOISP_NONE)
447 			return 0;
448 		v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
449 			"%s, toisp mode %d, hdr %d, stream on %d\n",
450 			__func__, priv->toisp_inf.link_mode, priv->hdr_cfg.hdr_mode, on);
451 		if (on) {
452 			ret = sditf_start_stream(priv);
453 		} else {
454 			ret = sditf_stop_stream(priv);
455 			sditf_free_buf(priv);
456 		}
457 
458 	}
459 	return ret;
460 }
461 
sditf_s_power(struct v4l2_subdev * sd,int on)462 static int sditf_s_power(struct v4l2_subdev *sd, int on)
463 {
464 	struct sditf_priv *priv = to_sditf_priv(sd);
465 	struct rkcif_device *cif_dev = priv->cif_dev;
466 	int ret = 0;
467 
468 	if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
469 		v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
470 			"%s, toisp mode %d, hdr %d, set power %d\n",
471 			__func__, priv->toisp_inf.link_mode, priv->hdr_cfg.hdr_mode, on);
472 		if (on)
473 			ret = pm_runtime_resume_and_get(cif_dev->dev);
474 		else
475 			pm_runtime_put(cif_dev->dev);
476 	}
477 	return ret;
478 }
479 
480 static const struct v4l2_subdev_pad_ops sditf_subdev_pad_ops = {
481 	.set_fmt = sditf_get_set_fmt,
482 	.get_fmt = sditf_get_set_fmt,
483 	.get_selection = sditf_get_selection,
484 	.get_mbus_config = sditf_g_mbus_config,
485 };
486 
487 static const struct v4l2_subdev_video_ops sditf_video_ops = {
488 	.g_frame_interval = sditf_g_frame_interval,
489 	.s_stream = sditf_s_stream,
490 };
491 
492 static const struct v4l2_subdev_core_ops sditf_core_ops = {
493 	.ioctl = sditf_ioctl,
494 #ifdef CONFIG_COMPAT
495 	.compat_ioctl32 = sditf_compat_ioctl32,
496 #endif
497 	.s_power = sditf_s_power,
498 };
499 
500 static const struct v4l2_subdev_ops sditf_subdev_ops = {
501 	.core = &sditf_core_ops,
502 	.video = &sditf_video_ops,
503 	.pad = &sditf_subdev_pad_ops,
504 };
505 
rkcif_sditf_attach_cifdev(struct sditf_priv * sditf)506 static int rkcif_sditf_attach_cifdev(struct sditf_priv *sditf)
507 {
508 	struct device_node *np;
509 	struct platform_device *pdev;
510 	struct rkcif_device *cif_dev;
511 
512 	np = of_parse_phandle(sditf->dev->of_node, "rockchip,cif", 0);
513 	if (!np || !of_device_is_available(np)) {
514 		dev_err(sditf->dev, "failed to get cif dev node\n");
515 		return -ENODEV;
516 	}
517 
518 	pdev = of_find_device_by_node(np);
519 	of_node_put(np);
520 	if (!pdev) {
521 		dev_err(sditf->dev, "failed to get cif dev from node\n");
522 		return -ENODEV;
523 	}
524 
525 	cif_dev = platform_get_drvdata(pdev);
526 	if (!cif_dev) {
527 		dev_err(sditf->dev, "failed attach cif dev\n");
528 		return -EINVAL;
529 	}
530 
531 	cif_dev->sditf = sditf;
532 	sditf->cif_dev = cif_dev;
533 
534 	return 0;
535 }
536 
rkcif_subdev_media_init(struct sditf_priv * priv)537 static int rkcif_subdev_media_init(struct sditf_priv *priv)
538 {
539 	struct rkcif_device *cif_dev = priv->cif_dev;
540 	int ret;
541 
542 	priv->pads.flags = MEDIA_PAD_FL_SOURCE;
543 	priv->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_COMPOSER;
544 	ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pads);
545 	if (ret < 0)
546 		return ret;
547 
548 	strncpy(priv->sd.name, dev_name(cif_dev->dev), sizeof(priv->sd.name));
549 	priv->cap_info.width = 0;
550 	priv->cap_info.height = 0;
551 	priv->mode.is_rdbk = 0;
552 	priv->toisp_inf.link_mode = TOISP_NONE;
553 	priv->toisp_inf.ch_info[0].is_valid = false;
554 	priv->toisp_inf.ch_info[1].is_valid = false;
555 	priv->toisp_inf.ch_info[2].is_valid = false;
556 	return 0;
557 }
558 
rkcif_subdev_probe(struct platform_device * pdev)559 static int rkcif_subdev_probe(struct platform_device *pdev)
560 {
561 	struct device *dev = &pdev->dev;
562 	struct v4l2_subdev *sd;
563 	struct sditf_priv *priv;
564 	int ret;
565 
566 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
567 	if (!priv)
568 		return -ENOMEM;
569 	priv->dev = dev;
570 
571 	sd = &priv->sd;
572 	v4l2_subdev_init(sd, &sditf_subdev_ops);
573 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
574 	snprintf(sd->name, sizeof(sd->name), "rockchip-cif-sditf");
575 	sd->dev = dev;
576 
577 	platform_set_drvdata(pdev, &sd->entity);
578 
579 	rkcif_sditf_attach_cifdev(priv);
580 	ret = rkcif_subdev_media_init(priv);
581 	if (ret < 0)
582 		return ret;
583 
584 	pm_runtime_enable(&pdev->dev);
585 	return 0;
586 }
587 
rkcif_subdev_remove(struct platform_device * pdev)588 static int rkcif_subdev_remove(struct platform_device *pdev)
589 {
590 	struct media_entity *me = platform_get_drvdata(pdev);
591 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(me);
592 
593 	media_entity_cleanup(&sd->entity);
594 
595 	pm_runtime_disable(&pdev->dev);
596 	return 0;
597 }
598 
sditf_runtime_suspend(struct device * dev)599 static int sditf_runtime_suspend(struct device *dev)
600 {
601 	return 0;
602 }
603 
sditf_runtime_resume(struct device * dev)604 static int sditf_runtime_resume(struct device *dev)
605 {
606 	return 0;
607 }
608 
609 static const struct dev_pm_ops rkcif_subdev_pm_ops = {
610 	SET_RUNTIME_PM_OPS(sditf_runtime_suspend,
611 			   sditf_runtime_resume, NULL)
612 };
613 
614 static const struct of_device_id rkcif_subdev_match_id[] = {
615 	{
616 		.compatible = "rockchip,rkcif-sditf",
617 	},
618 	{}
619 };
620 MODULE_DEVICE_TABLE(of, rkcif_subdev_match_id);
621 
622 struct platform_driver rkcif_subdev_driver = {
623 	.probe = rkcif_subdev_probe,
624 	.remove = rkcif_subdev_remove,
625 	.driver = {
626 		.name = "rkcif_sditf",
627 		.pm = &rkcif_subdev_pm_ops,
628 		.of_match_table = rkcif_subdev_match_id,
629 	},
630 };
631 EXPORT_SYMBOL(rkcif_subdev_driver);
632 
633 MODULE_AUTHOR("Rockchip Camera/ISP team");
634 MODULE_DESCRIPTION("Rockchip CIF platform driver");
635 MODULE_LICENSE("GPL v2");
636