1// SPDX-License-Identifier: GPL-2.0
2/*
3 * stf_capture.c
4 *
5 * StarFive Camera Subsystem - capture device
6 *
7 * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
8 */
9
10#include "stf-camss.h"
11
12static const char * const stf_cap_names[] = {
13	"capture_raw",
14	"capture_yuv",
15};
16
17static const struct stfcamss_format_info stf_wr_fmts[] = {
18	{
19		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
20		.pixelformat = V4L2_PIX_FMT_SRGGB10,
21		.planes = 1,
22		.vsub = { 1 },
23		.bpp = 16,
24	},
25	{
26		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
27		.pixelformat = V4L2_PIX_FMT_SGRBG10,
28		.planes = 1,
29		.vsub = { 1 },
30		.bpp = 16,
31	},
32	{
33		.code = MEDIA_BUS_FMT_SGBRG10_1X10,
34		.pixelformat = V4L2_PIX_FMT_SGBRG10,
35		.planes = 1,
36		.vsub = { 1 },
37		.bpp = 16,
38	},
39	{
40		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
41		.pixelformat = V4L2_PIX_FMT_SBGGR10,
42		.planes = 1,
43		.vsub = { 1 },
44		.bpp = 16,
45	},
46};
47
48static const struct stfcamss_format_info stf_isp_fmts[] = {
49	{
50		.code = MEDIA_BUS_FMT_YUYV8_1_5X8,
51		.pixelformat = V4L2_PIX_FMT_NV12,
52		.planes = 2,
53		.vsub = { 1, 2 },
54		.bpp = 8,
55	},
56};
57
58static inline struct stf_capture *to_stf_capture(struct stfcamss_video *video)
59{
60	return container_of(video, struct stf_capture, video);
61}
62
63static void stf_set_raw_addr(struct stfcamss *stfcamss, dma_addr_t addr)
64{
65	stf_syscon_reg_write(stfcamss, VIN_START_ADDR_O, (long)addr);
66	stf_syscon_reg_write(stfcamss, VIN_START_ADDR_N, (long)addr);
67}
68
69static void stf_set_yuv_addr(struct stfcamss *stfcamss,
70			     dma_addr_t y_addr, dma_addr_t uv_addr)
71{
72	stf_isp_reg_write(stfcamss, ISP_REG_Y_PLANE_START_ADDR, y_addr);
73	stf_isp_reg_write(stfcamss, ISP_REG_UV_PLANE_START_ADDR, uv_addr);
74}
75
76static void stf_init_addrs(struct stfcamss_video *video)
77{
78	struct stf_capture *cap = to_stf_capture(video);
79	struct stf_v_buf *output = &cap->buffers;
80	dma_addr_t addr0, addr1;
81
82	output->active_buf = 0;
83
84	if (!output->buf[0])
85		return;
86
87	addr0 = output->buf[0]->addr[0];
88	addr1 = output->buf[0]->addr[1];
89
90	if (cap->type == STF_CAPTURE_RAW)
91		stf_set_raw_addr(video->stfcamss, addr0);
92	else if (cap->type == STF_CAPTURE_YUV)
93		stf_set_yuv_addr(video->stfcamss, addr0, addr1);
94}
95
96static struct stfcamss_buffer *stf_buf_get_pending(struct stf_v_buf *output)
97{
98	struct stfcamss_buffer *buffer = NULL;
99
100	if (!list_empty(&output->pending_bufs)) {
101		buffer = list_first_entry(&output->pending_bufs,
102					  struct stfcamss_buffer,
103					  queue);
104		list_del(&buffer->queue);
105	}
106
107	return buffer;
108}
109
110static void stf_cap_s_cfg(struct stfcamss_video *video)
111{
112	struct stf_capture *cap = to_stf_capture(video);
113	struct stf_v_buf *output = &cap->buffers;
114	unsigned long flags;
115
116	spin_lock_irqsave(&output->lock, flags);
117
118	output->state = STF_OUTPUT_IDLE;
119	output->buf[0] = stf_buf_get_pending(output);
120
121	if (!output->buf[0] && output->buf[1]) {
122		output->buf[0] = output->buf[1];
123		output->buf[1] = NULL;
124	}
125
126	if (output->buf[0])
127		output->state = STF_OUTPUT_SINGLE;
128
129	output->sequence = 0;
130	stf_init_addrs(video);
131
132	spin_unlock_irqrestore(&output->lock, flags);
133}
134
135static int stf_cap_s_cleanup(struct stfcamss_video *video)
136{
137	struct stf_capture *cap = to_stf_capture(video);
138	struct stf_v_buf *output = &cap->buffers;
139	unsigned long flags;
140
141	spin_lock_irqsave(&output->lock, flags);
142
143	output->state = STF_OUTPUT_OFF;
144
145	spin_unlock_irqrestore(&output->lock, flags);
146
147	return 0;
148}
149
150static void stf_wr_data_en(struct stfcamss_video *video)
151{
152	struct stf_capture *cap = to_stf_capture(video);
153	struct stfcamss *stfcamss = cap->video.stfcamss;
154
155	stf_syscon_reg_set_bit(stfcamss, VIN_CHANNEL_SEL_EN, U0_VIN_AXIWR0_EN);
156}
157
158static void stf_wr_irq_enable(struct stfcamss_video *video)
159{
160	struct stf_capture *cap = to_stf_capture(video);
161	struct stfcamss *stfcamss = cap->video.stfcamss;
162
163	stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_M);
164}
165
166static void stf_wr_irq_disable(struct stfcamss_video *video)
167{
168	struct stf_capture *cap = to_stf_capture(video);
169	struct stfcamss *stfcamss = cap->video.stfcamss;
170
171	stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
172	stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
173	stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_M);
174}
175
176static void stf_channel_set(struct stfcamss_video *video)
177{
178	struct stf_capture *cap = to_stf_capture(video);
179	struct stfcamss *stfcamss = cap->video.stfcamss;
180	u32 val;
181
182	if (cap->type == STF_CAPTURE_RAW) {
183		val = stf_syscon_reg_read(stfcamss, VIN_CHANNEL_SEL_EN);
184		val &= ~U0_VIN_CHANNEL_SEL_MASK;
185		val |= CHANNEL(0);
186		stf_syscon_reg_write(stfcamss, VIN_CHANNEL_SEL_EN, val);
187
188		val = stf_syscon_reg_read(stfcamss, VIN_INRT_PIX_CFG);
189		val &= ~U0_VIN_PIX_CT_MASK;
190		val |= PIX_CT(1);
191
192		val &= ~U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS;
193		val |= PIXEL_HEIGH_BIT_SEL(0);
194
195		val &= ~U0_VIN_PIX_CNT_END_MASK;
196		val |= PIX_CNT_END(IMAGE_MAX_WIDTH / 4 - 1);
197
198		stf_syscon_reg_write(stfcamss, VIN_INRT_PIX_CFG, val);
199	} else if (cap->type == STF_CAPTURE_YUV) {
200		val = stf_syscon_reg_read(stfcamss, VIN_CFG_REG);
201		val &= ~U0_VIN_MIPI_BYTE_EN_ISP0_MASK;
202		val |= U0_VIN_MIPI_BYTE_EN_ISP0(0);
203
204		val &= ~U0_VIN_MIPI_CHANNEL_SEL0_MASK;
205		val |= U0_VIN_MIPI_CHANNEL_SEL0(0);
206
207		val &= ~U0_VIN_PIX_NUM_MASK;
208		val |= U0_VIN_PIX_NUM(0);
209
210		val &= ~U0_VIN_P_I_MIPI_HAEDER_EN0_MASK;
211		val |= U0_VIN_P_I_MIPI_HAEDER_EN0(1);
212
213		stf_syscon_reg_write(stfcamss, VIN_CFG_REG, val);
214	}
215}
216
217static void stf_capture_start(struct stfcamss_video *video)
218{
219	struct stf_capture *cap = to_stf_capture(video);
220
221	stf_channel_set(video);
222	if (cap->type == STF_CAPTURE_RAW) {
223		stf_wr_irq_enable(video);
224		stf_wr_data_en(video);
225	}
226
227	stf_cap_s_cfg(video);
228}
229
230static void stf_capture_stop(struct stfcamss_video *video)
231{
232	struct stf_capture *cap = to_stf_capture(video);
233
234	if (cap->type == STF_CAPTURE_RAW)
235		stf_wr_irq_disable(video);
236
237	stf_cap_s_cleanup(video);
238}
239
240static void stf_capture_init(struct stfcamss *stfcamss, struct stf_capture *cap)
241{
242	cap->buffers.state = STF_OUTPUT_OFF;
243	cap->buffers.buf[0] = NULL;
244	cap->buffers.buf[1] = NULL;
245	cap->buffers.active_buf = 0;
246	atomic_set(&cap->buffers.frame_skip, 4);
247	INIT_LIST_HEAD(&cap->buffers.pending_bufs);
248	INIT_LIST_HEAD(&cap->buffers.ready_bufs);
249	spin_lock_init(&cap->buffers.lock);
250
251	cap->video.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
252	cap->video.stfcamss = stfcamss;
253	cap->video.bpl_alignment = 16 * 8;
254
255	if (cap->type == STF_CAPTURE_RAW) {
256		cap->video.formats = stf_wr_fmts;
257		cap->video.nformats = ARRAY_SIZE(stf_wr_fmts);
258		cap->video.bpl_alignment = 8;
259	} else if (cap->type == STF_CAPTURE_YUV) {
260		cap->video.formats = stf_isp_fmts;
261		cap->video.nformats = ARRAY_SIZE(stf_isp_fmts);
262		cap->video.bpl_alignment = 1;
263	}
264}
265
266static void stf_buf_add_ready(struct stf_v_buf *output,
267			      struct stfcamss_buffer *buffer)
268{
269	INIT_LIST_HEAD(&buffer->queue);
270	list_add_tail(&buffer->queue, &output->ready_bufs);
271}
272
273static struct stfcamss_buffer *stf_buf_get_ready(struct stf_v_buf *output)
274{
275	struct stfcamss_buffer *buffer = NULL;
276
277	if (!list_empty(&output->ready_bufs)) {
278		buffer = list_first_entry(&output->ready_bufs,
279					  struct stfcamss_buffer,
280					  queue);
281		list_del(&buffer->queue);
282	}
283
284	return buffer;
285}
286
287static void stf_buf_add_pending(struct stf_v_buf *output,
288				struct stfcamss_buffer *buffer)
289{
290	INIT_LIST_HEAD(&buffer->queue);
291	list_add_tail(&buffer->queue, &output->pending_bufs);
292}
293
294static void stf_buf_update_on_last(struct stf_v_buf *output)
295{
296	switch (output->state) {
297	case STF_OUTPUT_CONTINUOUS:
298		output->state = STF_OUTPUT_SINGLE;
299		output->active_buf = !output->active_buf;
300		break;
301	case STF_OUTPUT_SINGLE:
302		output->state = STF_OUTPUT_STOPPING;
303		break;
304	default:
305		break;
306	}
307}
308
309static void stf_buf_update_on_next(struct stf_v_buf *output)
310{
311	switch (output->state) {
312	case STF_OUTPUT_CONTINUOUS:
313		output->active_buf = !output->active_buf;
314		break;
315	case STF_OUTPUT_SINGLE:
316	default:
317		break;
318	}
319}
320
321static void stf_buf_update_on_new(struct stfcamss_video *video,
322				  struct stfcamss_buffer *new_buf)
323{
324	struct stf_capture *cap = to_stf_capture(video);
325	struct stf_v_buf *output = &cap->buffers;
326
327	switch (output->state) {
328	case STF_OUTPUT_SINGLE:
329		stf_buf_add_pending(output, new_buf);
330		break;
331	case STF_OUTPUT_IDLE:
332		if (!output->buf[0]) {
333			output->buf[0] = new_buf;
334			stf_init_addrs(video);
335			output->state = STF_OUTPUT_SINGLE;
336		} else {
337			stf_buf_add_pending(output, new_buf);
338		}
339		break;
340	case STF_OUTPUT_STOPPING:
341		if (output->last_buffer) {
342			output->buf[output->active_buf] = output->last_buffer;
343			output->last_buffer = NULL;
344		}
345
346		output->state = STF_OUTPUT_SINGLE;
347		stf_buf_add_pending(output, new_buf);
348		break;
349	case STF_OUTPUT_CONTINUOUS:
350	default:
351		stf_buf_add_pending(output, new_buf);
352		break;
353	}
354}
355
356static void stf_buf_flush(struct stf_v_buf *output, enum vb2_buffer_state state)
357{
358	struct stfcamss_buffer *buf;
359	struct stfcamss_buffer *t;
360
361	list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) {
362		vb2_buffer_done(&buf->vb.vb2_buf, state);
363		list_del(&buf->queue);
364	}
365	list_for_each_entry_safe(buf, t, &output->ready_bufs, queue) {
366		vb2_buffer_done(&buf->vb.vb2_buf, state);
367		list_del(&buf->queue);
368	}
369}
370
371static void stf_buf_done(struct stf_v_buf *output)
372{
373	struct stfcamss_buffer *ready_buf;
374	u64 ts = ktime_get_ns();
375	unsigned long flags;
376
377	if (output->state == STF_OUTPUT_OFF ||
378	    output->state == STF_OUTPUT_RESERVED)
379		return;
380
381	spin_lock_irqsave(&output->lock, flags);
382
383	while ((ready_buf = stf_buf_get_ready(output))) {
384		ready_buf->vb.vb2_buf.timestamp = ts;
385		ready_buf->vb.sequence = output->sequence++;
386
387		vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
388	}
389
390	spin_unlock_irqrestore(&output->lock, flags);
391}
392
393static void stf_change_buffer(struct stf_v_buf *output)
394{
395	struct stf_capture *cap = container_of(output, struct stf_capture,
396					       buffers);
397	struct stfcamss *stfcamss = cap->video.stfcamss;
398	struct stfcamss_buffer *ready_buf;
399	dma_addr_t *new_addr;
400	unsigned long flags;
401	u32 active_index;
402
403	if (output->state == STF_OUTPUT_OFF ||
404	    output->state == STF_OUTPUT_STOPPING ||
405	    output->state == STF_OUTPUT_RESERVED ||
406	    output->state == STF_OUTPUT_IDLE)
407		return;
408
409	spin_lock_irqsave(&output->lock, flags);
410
411	active_index = output->active_buf;
412
413	ready_buf = output->buf[active_index];
414	if (!ready_buf) {
415		dev_dbg(stfcamss->dev, "missing ready buf %d %d.\n",
416			active_index, output->state);
417		active_index = !active_index;
418		ready_buf = output->buf[active_index];
419		if (!ready_buf) {
420			dev_dbg(stfcamss->dev,
421				"missing ready buf2 %d %d.\n",
422				active_index, output->state);
423			goto out_unlock;
424		}
425	}
426
427	/* Get next buffer */
428	output->buf[active_index] = stf_buf_get_pending(output);
429	if (!output->buf[active_index]) {
430		new_addr = ready_buf->addr;
431		stf_buf_update_on_last(output);
432	} else {
433		new_addr = output->buf[active_index]->addr;
434		stf_buf_update_on_next(output);
435	}
436
437	if (output->state == STF_OUTPUT_STOPPING) {
438		output->last_buffer = ready_buf;
439	} else {
440		if (cap->type == STF_CAPTURE_RAW)
441			stf_set_raw_addr(stfcamss, new_addr[0]);
442		else if (cap->type == STF_CAPTURE_YUV)
443			stf_set_yuv_addr(stfcamss, new_addr[0], new_addr[1]);
444
445		stf_buf_add_ready(output, ready_buf);
446	}
447
448out_unlock:
449	spin_unlock_irqrestore(&output->lock, flags);
450}
451
452irqreturn_t stf_wr_irq_handler(int irq, void *priv)
453{
454	struct stfcamss *stfcamss = priv;
455	struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_RAW];
456
457	if (atomic_dec_if_positive(&cap->buffers.frame_skip) < 0) {
458		stf_change_buffer(&cap->buffers);
459		stf_buf_done(&cap->buffers);
460	}
461
462	stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
463	stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
464
465	return IRQ_HANDLED;
466}
467
468irqreturn_t stf_isp_irq_handler(int irq, void *priv)
469{
470	struct stfcamss *stfcamss = priv;
471	struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_YUV];
472	u32 status;
473
474	status = stf_isp_reg_read(stfcamss, ISP_REG_ISP_CTRL_0);
475	if (status & ISPC_ISP) {
476		if (status & ISPC_ENUO)
477			stf_buf_done(&cap->buffers);
478
479		stf_isp_reg_write(stfcamss, ISP_REG_ISP_CTRL_0,
480				  (status & ~ISPC_INT_ALL_MASK) |
481				  ISPC_ISP | ISPC_CSI | ISPC_SC);
482	}
483
484	return IRQ_HANDLED;
485}
486
487irqreturn_t stf_line_irq_handler(int irq, void *priv)
488{
489	struct stfcamss *stfcamss = priv;
490	struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_YUV];
491	u32 status;
492
493	status = stf_isp_reg_read(stfcamss, ISP_REG_ISP_CTRL_0);
494	if (status & ISPC_LINE) {
495		if (atomic_dec_if_positive(&cap->buffers.frame_skip) < 0) {
496			if ((status & ISPC_ENUO))
497				stf_change_buffer(&cap->buffers);
498		}
499
500		stf_isp_reg_set_bit(stfcamss, ISP_REG_CSIINTS,
501				    CSI_INTS_MASK, CSI_INTS(0x3));
502		stf_isp_reg_set_bit(stfcamss, ISP_REG_IESHD,
503				    SHAD_UP_M | SHAD_UP_EN, 0x3);
504
505		stf_isp_reg_write(stfcamss, ISP_REG_ISP_CTRL_0,
506				  (status & ~ISPC_INT_ALL_MASK) | ISPC_LINE);
507	}
508
509	return IRQ_HANDLED;
510}
511
512static int stf_queue_buffer(struct stfcamss_video *video,
513			    struct stfcamss_buffer *buf)
514{
515	struct stf_capture *cap = to_stf_capture(video);
516	struct stf_v_buf *v_bufs = &cap->buffers;
517	unsigned long flags;
518
519	spin_lock_irqsave(&v_bufs->lock, flags);
520	stf_buf_update_on_new(video, buf);
521	spin_unlock_irqrestore(&v_bufs->lock, flags);
522
523	return 0;
524}
525
526static int stf_flush_buffers(struct stfcamss_video *video,
527			     enum vb2_buffer_state state)
528{
529	struct stf_capture *cap = to_stf_capture(video);
530	struct stf_v_buf *v_bufs = &cap->buffers;
531	unsigned long flags;
532	unsigned int i;
533
534	spin_lock_irqsave(&v_bufs->lock, flags);
535
536	stf_buf_flush(v_bufs, state);
537
538	for (i = 0; i < ARRAY_SIZE(v_bufs->buf); i++) {
539		if (v_bufs->buf[i])
540			vb2_buffer_done(&v_bufs->buf[i]->vb.vb2_buf, state);
541
542		v_bufs->buf[i] = NULL;
543	}
544
545	if (v_bufs->last_buffer) {
546		vb2_buffer_done(&v_bufs->last_buffer->vb.vb2_buf, state);
547		v_bufs->last_buffer = NULL;
548	}
549
550	spin_unlock_irqrestore(&v_bufs->lock, flags);
551	return 0;
552}
553
554static const struct stfcamss_video_ops stf_capture_ops = {
555	.queue_buffer = stf_queue_buffer,
556	.flush_buffers = stf_flush_buffers,
557	.start_streaming = stf_capture_start,
558	.stop_streaming = stf_capture_stop,
559};
560
561static void stf_capture_unregister_one(struct stf_capture *cap)
562{
563	if (!video_is_registered(&cap->video.vdev))
564		return;
565
566	media_entity_cleanup(&cap->video.vdev.entity);
567	vb2_video_unregister_device(&cap->video.vdev);
568}
569
570void stf_capture_unregister(struct stfcamss *stfcamss)
571{
572	struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
573	struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
574
575	stf_capture_unregister_one(cap_raw);
576	stf_capture_unregister_one(cap_yuv);
577}
578
579int stf_capture_register(struct stfcamss *stfcamss,
580			 struct v4l2_device *v4l2_dev)
581{
582	unsigned int i;
583	int ret;
584
585	for (i = 0; i < ARRAY_SIZE(stfcamss->captures); i++) {
586		struct stf_capture *capture = &stfcamss->captures[i];
587
588		capture->type = i;
589		capture->video.ops = &stf_capture_ops;
590		stf_capture_init(stfcamss, capture);
591
592		ret = stf_video_register(&capture->video, v4l2_dev,
593					 stf_cap_names[i]);
594		if (ret < 0) {
595			dev_err(stfcamss->dev,
596				"Failed to register video node: %d\n", ret);
597			stf_capture_unregister(stfcamss);
598			return ret;
599		}
600	}
601
602	return 0;
603}
604