xref: /OK3568_Linux_fs/kernel/drivers/media/platform/rockchip/ispp/ispp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
3 
4 #include <linux/compat.h>
5 #include <linux/delay.h>
6 #include <linux/interrupt.h>
7 #include <linux/iommu.h>
8 #include <linux/pm_runtime.h>
9 #include <linux/videodev2.h>
10 #include <media/media-entity.h>
11 #include <media/videobuf2-dma-contig.h>
12 #include <media/v4l2-event.h>
13 
14 #include "dev.h"
15 #include "regs.h"
16 
cal_fec_mesh(u32 width,u32 height,u32 mode)17 u32 cal_fec_mesh(u32 width, u32 height, u32 mode)
18 {
19 	u32 mesh_size, mesh_left_height;
20 	u32 w = ALIGN(width, 32);
21 	u32 h = ALIGN(height, 32);
22 	u32 spb_num = (h + 127) >> 7;
23 	u32 left_height = h & 127;
24 	u32 mesh_width = mode ? (w / 32 + 1) : (w / 16 + 1);
25 	u32 mesh_height = mode ? 9 : 17;
26 
27 	if (!left_height)
28 		left_height = 128;
29 	mesh_left_height = mode ? (left_height / 16 + 1) :
30 				(left_height / 8 + 1);
31 	mesh_size = (spb_num - 1) * mesh_width * mesh_height +
32 		mesh_width * mesh_left_height;
33 
34 	return mesh_size;
35 }
36 
37 static const struct isppsd_fmt rkispp_formats[] = {
38 	{
39 		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
40 		.fourcc = V4L2_PIX_FMT_NV16,
41 		.wr_fmt = FMT_YUV422,
42 	},
43 };
44 
find_fmt(u32 mbus_code)45 static const struct isppsd_fmt *find_fmt(u32 mbus_code)
46 {
47 	const struct isppsd_fmt *fmt;
48 	int i, array_size = ARRAY_SIZE(rkispp_formats);
49 
50 	for (i = 0; i < array_size; i++) {
51 		fmt = &rkispp_formats[i];
52 		if (fmt->mbus_code == mbus_code)
53 			return fmt;
54 	}
55 
56 	return NULL;
57 }
58 
rkispp_subdev_link_setup(struct media_entity * entity,const struct media_pad * local,const struct media_pad * remote,u32 flags)59 static int rkispp_subdev_link_setup(struct media_entity *entity,
60 				    const struct media_pad *local,
61 				    const struct media_pad *remote,
62 				    u32 flags)
63 {
64 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
65 	struct rkispp_subdev *ispp_sdev;
66 	struct rkispp_device *dev;
67 	struct rkispp_stream_vdev *vdev;
68 	struct rkispp_stream *stream = NULL;
69 
70 	if (local->index != RKISPP_PAD_SINK &&
71 	    local->index != RKISPP_PAD_SOURCE)
72 		return 0;
73 
74 	if (!sd)
75 		return -ENODEV;
76 	ispp_sdev = v4l2_get_subdevdata(sd);
77 	dev = ispp_sdev->dev;
78 	vdev = &dev->stream_vdev;
79 
80 	if (!strcmp(remote->entity->name, II_VDEV_NAME)) {
81 		stream = &vdev->stream[STREAM_II];
82 		if (ispp_sdev->state & ISPP_START)
83 			return -EBUSY;
84 		if (flags & MEDIA_LNK_FL_ENABLED)
85 			dev->inp = INP_DDR;
86 		else if (ispp_sdev->remote_sd)
87 			dev->inp = INP_ISP;
88 		else
89 			dev->inp = INP_INVAL;
90 		stream->linked = flags & MEDIA_LNK_FL_ENABLED;
91 		v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev,
92 			 "input:%d\n", dev->inp);
93 	} else if (!strcmp(remote->entity->name, MB_VDEV_NAME)) {
94 		stream = &vdev->stream[STREAM_MB];
95 	} else if (!strcmp(remote->entity->name, S0_VDEV_NAME)) {
96 		stream = &vdev->stream[STREAM_S0];
97 	} else if (!strcmp(remote->entity->name, S1_VDEV_NAME)) {
98 		stream = &vdev->stream[STREAM_S1];
99 	} else if (!strcmp(remote->entity->name, S2_VDEV_NAME)) {
100 		stream = &vdev->stream[STREAM_S2];
101 	}
102 	if (stream && dev->stream_sync) {
103 		stream->linked = flags & MEDIA_LNK_FL_ENABLED;
104 		v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev,
105 			 "stream:%d linked:%d\n",
106 			 stream->id, stream->linked);
107 	}
108 	return 0;
109 }
110 
rkispp_sd_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)111 static int rkispp_sd_get_fmt(struct v4l2_subdev *sd,
112 			     struct v4l2_subdev_pad_config *cfg,
113 			     struct v4l2_subdev_format *fmt)
114 {
115 	struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
116 	struct v4l2_mbus_framefmt *mf;
117 	const struct isppsd_fmt *ispp_fmt;
118 	int ret = 0;
119 
120 	if (!fmt)
121 		goto err;
122 
123 	if (fmt->pad != RKISPP_PAD_SINK &&
124 	    fmt->pad != RKISPP_PAD_SOURCE)
125 		goto err;
126 
127 	mf = &fmt->format;
128 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
129 		if (!cfg)
130 			goto err;
131 		mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
132 	}
133 
134 	*mf = ispp_sdev->in_fmt;
135 	if (fmt->pad == RKISPP_PAD_SINK && ispp_sdev->dev->inp == INP_ISP) {
136 		ret = v4l2_subdev_call(ispp_sdev->remote_sd,
137 				       pad, get_fmt, cfg, fmt);
138 		if (!ret) {
139 			ispp_fmt = find_fmt(fmt->format.code);
140 			if (!ispp_fmt)
141 				goto err;
142 			if (ispp_sdev->in_fmt.width != mf->width ||
143 			    ispp_sdev->in_fmt.height != mf->height) {
144 				ispp_sdev->out_fmt = *ispp_fmt;
145 				ispp_sdev->out_fmt.width = mf->width;
146 				ispp_sdev->out_fmt.height = mf->height;
147 			}
148 			ispp_sdev->in_fmt = *mf;
149 		}
150 	} else {
151 		*mf = ispp_sdev->in_fmt;
152 		mf->width = ispp_sdev->out_fmt.width;
153 		mf->height = ispp_sdev->out_fmt.height;
154 	}
155 	return ret;
156 err:
157 	return -EINVAL;
158 }
159 
rkispp_sd_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)160 static int rkispp_sd_set_fmt(struct v4l2_subdev *sd,
161 			     struct v4l2_subdev_pad_config *cfg,
162 			     struct v4l2_subdev_format *fmt)
163 {
164 	struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
165 	struct v4l2_mbus_framefmt *mf;
166 
167 	if (!fmt)
168 		return -EINVAL;
169 
170 	/* format from isp output */
171 	if (fmt->pad == RKISPP_PAD_SINK && ispp_sdev->dev->inp == INP_ISP)
172 		return 0;
173 
174 	mf = &fmt->format;
175 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
176 		if (!cfg)
177 			return -EINVAL;
178 		mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
179 	}
180 
181 	if (fmt->pad == RKISPP_PAD_SINK) {
182 		ispp_sdev->in_fmt = *mf;
183 	} else {
184 		ispp_sdev->out_fmt.width = mf->width;
185 		ispp_sdev->out_fmt.height = mf->height;
186 	}
187 
188 	return 0;
189 }
190 
rkispp_sd_s_stream(struct v4l2_subdev * sd,int on)191 static int rkispp_sd_s_stream(struct v4l2_subdev *sd, int on)
192 {
193 	struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
194 	struct rkispp_device *dev = ispp_sdev->dev;
195 	int ret = 0;
196 
197 	v4l2_dbg(1, rkispp_debug, &ispp_sdev->dev->v4l2_dev,
198 		 "s_stream on:%d\n", on);
199 
200 	if (on) {
201 		ispp_sdev->state = ISPP_START;
202 		ispp_sdev->frm_sync_seq = -1;
203 		ispp_sdev->frame_timestamp = 0;
204 		rkispp_event_handle(dev, CMD_STREAM, &ispp_sdev->state);
205 	}
206 
207 	if (dev->inp == INP_ISP)
208 		ret = v4l2_subdev_call(ispp_sdev->remote_sd, video, s_stream, on);
209 
210 	if ((on && ret) || (!on && !ret)) {
211 		ispp_sdev->state = ISPP_STOP;
212 		if (dev->stream_vdev.monitor.is_en) {
213 			dev->stream_vdev.monitor.is_en = false;
214 			if (!completion_done(&dev->stream_vdev.monitor.cmpl))
215 				complete(&dev->stream_vdev.monitor.cmpl);
216 			if (!completion_done(&dev->stream_vdev.monitor.tnr.cmpl))
217 				complete(&dev->stream_vdev.monitor.tnr.cmpl);
218 			if (!completion_done(&dev->stream_vdev.monitor.nr.cmpl))
219 				complete(&dev->stream_vdev.monitor.nr.cmpl);
220 			if (!completion_done(&dev->stream_vdev.monitor.fec.cmpl))
221 				complete(&dev->stream_vdev.monitor.fec.cmpl);
222 		}
223 		rkispp_event_handle(dev, CMD_STREAM, &ispp_sdev->state);
224 	}
225 	return ret;
226 }
227 
rkispp_sd_s_rx_buffer(struct v4l2_subdev * sd,void * buf,unsigned int * size)228 static int rkispp_sd_s_rx_buffer(struct v4l2_subdev *sd,
229 				 void *buf, unsigned int *size)
230 {
231 	struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
232 	struct rkispp_device *dev = ispp_sdev->dev;
233 	u32 cmd = CMD_INIT_POOL;
234 
235 	/* size isn't using now */
236 	if (!buf)
237 		return -EINVAL;
238 
239 	if (ispp_sdev->state == ISPP_START) {
240 		struct rkisp_ispp_buf *dbufs = buf;
241 		struct rkispp_stream_vdev *vdev = &dev->stream_vdev;
242 		u64 ns = ktime_get_ns();
243 
244 		vdev->dbg.interval = ns - vdev->dbg.timestamp;
245 		vdev->dbg.timestamp = ns;
246 		vdev->dbg.delay = ns - dbufs->frame_timestamp;
247 		vdev->dbg.id = dbufs->frame_id;
248 		cmd = CMD_QUEUE_DMABUF;
249 	}
250 
251 	return rkispp_event_handle(dev, cmd, buf);
252 }
253 
rkispp_sd_s_power(struct v4l2_subdev * sd,int on)254 static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on)
255 {
256 	struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
257 	struct rkispp_device *ispp_dev = ispp_sdev->dev;
258 	int ret;
259 
260 	v4l2_dbg(1, rkispp_debug, &ispp_dev->v4l2_dev,
261 		 "s_power on:%d\n", on);
262 	if (on) {
263 		if (ispp_dev->inp == INP_ISP) {
264 			struct v4l2_subdev_format fmt;
265 
266 			/* update format, if ispp input change */
267 			fmt.pad = RKISPP_PAD_SINK;
268 			fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
269 			ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
270 			if (ret) {
271 				v4l2_err(&ispp_dev->v4l2_dev,
272 					 "%s get format fail:%d\n",
273 					 __func__, ret);
274 				return ret;
275 			}
276 
277 			ret = v4l2_subdev_call(ispp_sdev->remote_sd,
278 					       core, s_power, 1);
279 			if (ret < 0) {
280 				v4l2_err(&ispp_dev->v4l2_dev,
281 					 "%s set isp power on fail:%d\n",
282 					 __func__, ret);
283 				return ret;
284 			}
285 		}
286 		ret = pm_runtime_get_sync(ispp_dev->dev);
287 		if (ret < 0) {
288 			v4l2_err(&ispp_dev->v4l2_dev,
289 				 "%s runtime get failed:%d\n",
290 				 __func__, ret);
291 			if (ispp_dev->inp == INP_ISP)
292 				v4l2_subdev_call(ispp_sdev->remote_sd,
293 						 core, s_power, 0);
294 			return ret;
295 		}
296 	} else {
297 		if (ispp_dev->inp == INP_ISP)
298 			v4l2_subdev_call(ispp_sdev->remote_sd, core, s_power, 0);
299 		ret = pm_runtime_put_sync(ispp_dev->dev);
300 		if (ret < 0)
301 			v4l2_err(&ispp_dev->v4l2_dev,
302 				 "%s runtime put failed:%d\n",
303 				 __func__, ret);
304 	}
305 
306 	return ret;
307 }
308 
rkispp_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)309 static long rkispp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
310 {
311 	struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
312 	struct rkispp_device *ispp_dev = ispp_sdev->dev;
313 	struct rkispp_fecbuf_info *fecbuf;
314 	struct rkispp_fecbuf_size *fecsize;
315 	struct rkisp_ispp_reg **reg_buf;
316 	bool *rkispp_reg_withstream;
317 	long ret = 0;
318 
319 	if (!arg)
320 		return -EINVAL;
321 
322 	switch (cmd) {
323 	case RKISPP_CMD_SET_INIT_MODULE:
324 		ispp_dev->stream_vdev.module_ens = *((int *)arg);
325 		if (ispp_dev->hw_dev->is_fec_ext)
326 			ispp_dev->stream_vdev.module_ens &= ~ISPP_MODULE_FEC_ST;
327 		break;
328 	case RKISPP_CMD_GET_FECBUF_INFO:
329 		fecbuf = (struct rkispp_fecbuf_info *)arg;
330 		rkispp_params_get_fecbuf_inf(&ispp_dev->params_vdev[PARAM_VDEV_FEC], fecbuf);
331 		break;
332 	case RKISPP_CMD_SET_FECBUF_SIZE:
333 		fecsize = (struct rkispp_fecbuf_size *)arg;
334 		rkispp_params_set_fecbuf_size(&ispp_dev->params_vdev[PARAM_VDEV_FEC], fecsize);
335 		break;
336 	case RKISP_ISPP_CMD_REQUEST_REGBUF:
337 		reg_buf = (struct rkisp_ispp_reg **)arg;
338 		rkispp_request_regbuf(ispp_dev, reg_buf);
339 		break;
340 	case RKISP_ISPP_CMD_GET_REG_WITHSTREAM:
341 		rkispp_reg_withstream = arg;
342 		*rkispp_reg_withstream = rkispp_is_reg_withstream_global();
343 		break;
344 	#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISPP_VERSION_V10)
345 	case RKISPP_CMD_GET_TNRBUF_FD:
346 		ret = rkispp_get_tnrbuf_fd(ispp_dev, (struct rkispp_buf_idxfd *)arg);
347 		break;
348 	case RKISPP_CMD_GET_NRBUF_FD:
349 		ret = rkispp_get_nrbuf_fd(ispp_dev, (struct rkispp_buf_idxfd *)arg);
350 		break;
351 	case RKISPP_CMD_TRIGGER_MODE:
352 		rkispp_set_trigger_mode(ispp_dev, (struct rkispp_trigger_mode *)arg);
353 		break;
354 	#endif
355 	default:
356 		ret = -ENOIOCTLCMD;
357 	}
358 
359 	return ret;
360 }
361 
362 #ifdef CONFIG_COMPAT
rkispp_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)363 static long rkispp_compat_ioctl32(struct v4l2_subdev *sd,
364 				  unsigned int cmd, unsigned long arg)
365 {
366 	void __user *up = compat_ptr(arg);
367 	struct rkispp_fecbuf_info fecbuf;
368 	struct rkispp_fecbuf_size fecsize;
369 	struct rkispp_buf_idxfd idxfd;
370 	struct rkispp_trigger_mode t_mode;
371 	long ret = 0;
372 
373 	if (!up)
374 		return -EINVAL;
375 
376 	switch (cmd) {
377 	case RKISPP_CMD_GET_FECBUF_INFO:
378 		ret = rkispp_ioctl(sd, cmd, &fecbuf);
379 		if (!ret && copy_to_user(up, &fecbuf, sizeof(fecbuf)))
380 			ret = -EFAULT;
381 		break;
382 	case RKISPP_CMD_SET_FECBUF_SIZE:
383 		if (copy_from_user(&fecsize, up, sizeof(fecsize)))
384 			return -EFAULT;
385 		ret = rkispp_ioctl(sd, cmd, &fecsize);
386 		break;
387 	case RKISPP_CMD_GET_TNRBUF_FD:
388 	case RKISPP_CMD_GET_NRBUF_FD:
389 		ret = rkispp_ioctl(sd, cmd, &idxfd);
390 		if (!ret && copy_to_user(up, &idxfd, sizeof(idxfd)))
391 			ret = -EFAULT;
392 		break;
393 	case RKISPP_CMD_TRIGGER_MODE:
394 		if (copy_from_user(&t_mode, up, sizeof(t_mode)))
395 			return -EFAULT;
396 		ret = rkispp_ioctl(sd, cmd, &t_mode);
397 		break;
398 	default:
399 		ret = -ENOIOCTLCMD;
400 	}
401 
402 	return ret;
403 }
404 #endif
405 
rkispp_subscribe_event(struct v4l2_subdev * sd,struct v4l2_fh * fh,struct v4l2_event_subscription * sub)406 static int rkispp_subscribe_event(struct v4l2_subdev *sd,
407 				  struct v4l2_fh *fh,
408 				  struct v4l2_event_subscription *sub)
409 {
410 	switch (sub->type) {
411 	case RKISPP_V4L2_EVENT_TNR_COMPLETE:
412 		return v4l2_event_subscribe(fh, sub, RKISPP_BUF_MAX, NULL);
413 	default:
414 		return -EINVAL;
415 	}
416 }
417 
418 static const struct media_entity_operations rkispp_sd_media_ops = {
419 	.link_setup = rkispp_subdev_link_setup,
420 	.link_validate = v4l2_subdev_link_validate,
421 };
422 
423 static const struct v4l2_subdev_pad_ops rkispp_sd_pad_ops = {
424 	.get_fmt = rkispp_sd_get_fmt,
425 	.set_fmt = rkispp_sd_set_fmt,
426 };
427 
428 static const struct v4l2_subdev_video_ops rkispp_sd_video_ops = {
429 	.s_stream = rkispp_sd_s_stream,
430 	.s_rx_buffer = rkispp_sd_s_rx_buffer,
431 };
432 
433 static const struct v4l2_subdev_core_ops rkispp_sd_core_ops = {
434 	.s_power = rkispp_sd_s_power,
435 	.ioctl = rkispp_ioctl,
436 #ifdef CONFIG_COMPAT
437 	.compat_ioctl32 = rkispp_compat_ioctl32,
438 #endif
439 	.subscribe_event = rkispp_subscribe_event,
440 	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
441 };
442 
443 static struct v4l2_subdev_ops rkispp_sd_ops = {
444 	.core = &rkispp_sd_core_ops,
445 	.video = &rkispp_sd_video_ops,
446 	.pad = &rkispp_sd_pad_ops,
447 };
448 
rkispp_register_subdev(struct rkispp_device * dev,struct v4l2_device * v4l2_dev)449 int rkispp_register_subdev(struct rkispp_device *dev,
450 			   struct v4l2_device *v4l2_dev)
451 {
452 	struct rkispp_subdev *ispp_sdev = &dev->ispp_sdev;
453 	struct v4l2_subdev *sd;
454 	int ret;
455 
456 	memset(ispp_sdev, 0, sizeof(*ispp_sdev));
457 	ispp_sdev->dev = dev;
458 	sd = &ispp_sdev->sd;
459 	ispp_sdev->state = ISPP_STOP;
460 	v4l2_subdev_init(sd, &rkispp_sd_ops);
461 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
462 	sd->entity.ops = &rkispp_sd_media_ops;
463 	snprintf(sd->name, sizeof(sd->name), "rkispp-subdev");
464 	sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_COMPOSER;
465 	ispp_sdev->pads[RKISPP_PAD_SINK].flags =
466 		MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
467 	ispp_sdev->pads[RKISPP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
468 	ispp_sdev->pads[RKISPP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
469 	ispp_sdev->pads[RKISPP_PAD_SOURCE_STATS].flags = MEDIA_PAD_FL_SOURCE;
470 
471 	ret = media_entity_pads_init(&sd->entity, RKISPP_PAD_MAX,
472 				     ispp_sdev->pads);
473 	if (ret < 0)
474 		return ret;
475 	sd->owner = THIS_MODULE;
476 	v4l2_set_subdevdata(sd, ispp_sdev);
477 	sd->grp_id = GRP_ID_ISPP;
478 	ret = v4l2_device_register_subdev(v4l2_dev, sd);
479 	if (ret < 0)
480 		goto free_media;
481 
482 	ret = v4l2_device_register_subdev_nodes(v4l2_dev);
483 	if (ret < 0)
484 		goto free_subdev;
485 	return ret;
486 free_subdev:
487 	v4l2_device_unregister_subdev(sd);
488 free_media:
489 	media_entity_cleanup(&sd->entity);
490 	v4l2_err(sd, "Failed to register subdev, ret:%d\n", ret);
491 	return ret;
492 }
493 
rkispp_unregister_subdev(struct rkispp_device * dev)494 void rkispp_unregister_subdev(struct rkispp_device *dev)
495 {
496 	struct v4l2_subdev *sd = &dev->ispp_sdev.sd;
497 
498 	v4l2_device_unregister_subdev(sd);
499 	media_entity_cleanup(&sd->entity);
500 }
501