xref: /linux/drivers/media/platform/rockchip/rkcif/rkcif-stream.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1*501802e2SMichael Riesch // SPDX-License-Identifier: GPL-2.0
2*501802e2SMichael Riesch /*
3*501802e2SMichael Riesch  * Rockchip Camera Interface (CIF) Driver
4*501802e2SMichael Riesch  *
5*501802e2SMichael Riesch  * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
6*501802e2SMichael Riesch  * Copyright (C) 2025 Collabora, Ltd.
7*501802e2SMichael Riesch  */
8*501802e2SMichael Riesch 
9*501802e2SMichael Riesch #include <linux/pm_runtime.h>
10*501802e2SMichael Riesch 
11*501802e2SMichael Riesch #include <media/v4l2-common.h>
12*501802e2SMichael Riesch #include <media/v4l2-fwnode.h>
13*501802e2SMichael Riesch #include <media/v4l2-ioctl.h>
14*501802e2SMichael Riesch #include <media/v4l2-mc.h>
15*501802e2SMichael Riesch #include <media/v4l2-subdev.h>
16*501802e2SMichael Riesch #include <media/videobuf2-dma-contig.h>
17*501802e2SMichael Riesch 
18*501802e2SMichael Riesch #include "rkcif-common.h"
19*501802e2SMichael Riesch #include "rkcif-stream.h"
20*501802e2SMichael Riesch 
21*501802e2SMichael Riesch #define CIF_REQ_BUFS_MIN 1
22*501802e2SMichael Riesch #define CIF_MIN_WIDTH	 64
23*501802e2SMichael Riesch #define CIF_MIN_HEIGHT	 64
24*501802e2SMichael Riesch #define CIF_MAX_WIDTH	 8192
25*501802e2SMichael Riesch #define CIF_MAX_HEIGHT	 8192
26*501802e2SMichael Riesch 
27*501802e2SMichael Riesch static inline struct rkcif_buffer *to_rkcif_buffer(struct vb2_v4l2_buffer *vb)
28*501802e2SMichael Riesch {
29*501802e2SMichael Riesch 	return container_of(vb, struct rkcif_buffer, vb);
30*501802e2SMichael Riesch }
31*501802e2SMichael Riesch 
32*501802e2SMichael Riesch static inline struct rkcif_stream *to_rkcif_stream(struct video_device *vdev)
33*501802e2SMichael Riesch {
34*501802e2SMichael Riesch 	return container_of(vdev, struct rkcif_stream, vdev);
35*501802e2SMichael Riesch }
36*501802e2SMichael Riesch 
37*501802e2SMichael Riesch static struct rkcif_buffer *rkcif_stream_pop_buffer(struct rkcif_stream *stream)
38*501802e2SMichael Riesch {
39*501802e2SMichael Riesch 	struct rkcif_buffer *buffer;
40*501802e2SMichael Riesch 
41*501802e2SMichael Riesch 	guard(spinlock_irqsave)(&stream->driver_queue_lock);
42*501802e2SMichael Riesch 
43*501802e2SMichael Riesch 	if (list_empty(&stream->driver_queue))
44*501802e2SMichael Riesch 		return NULL;
45*501802e2SMichael Riesch 
46*501802e2SMichael Riesch 	buffer = list_first_entry(&stream->driver_queue, struct rkcif_buffer,
47*501802e2SMichael Riesch 				  queue);
48*501802e2SMichael Riesch 	list_del(&buffer->queue);
49*501802e2SMichael Riesch 
50*501802e2SMichael Riesch 	return buffer;
51*501802e2SMichael Riesch }
52*501802e2SMichael Riesch 
53*501802e2SMichael Riesch static void rkcif_stream_push_buffer(struct rkcif_stream *stream,
54*501802e2SMichael Riesch 				     struct rkcif_buffer *buffer)
55*501802e2SMichael Riesch {
56*501802e2SMichael Riesch 	guard(spinlock_irqsave)(&stream->driver_queue_lock);
57*501802e2SMichael Riesch 
58*501802e2SMichael Riesch 	list_add_tail(&buffer->queue, &stream->driver_queue);
59*501802e2SMichael Riesch }
60*501802e2SMichael Riesch 
61*501802e2SMichael Riesch static inline void rkcif_stream_return_buffer(struct rkcif_buffer *buffer,
62*501802e2SMichael Riesch 					      enum vb2_buffer_state state)
63*501802e2SMichael Riesch {
64*501802e2SMichael Riesch 	struct vb2_v4l2_buffer *vb = &buffer->vb;
65*501802e2SMichael Riesch 
66*501802e2SMichael Riesch 	vb2_buffer_done(&vb->vb2_buf, state);
67*501802e2SMichael Riesch }
68*501802e2SMichael Riesch 
69*501802e2SMichael Riesch static void rkcif_stream_complete_buffer(struct rkcif_stream *stream,
70*501802e2SMichael Riesch 					 struct rkcif_buffer *buffer)
71*501802e2SMichael Riesch {
72*501802e2SMichael Riesch 	struct vb2_v4l2_buffer *vb = &buffer->vb;
73*501802e2SMichael Riesch 
74*501802e2SMichael Riesch 	vb->vb2_buf.timestamp = ktime_get_ns();
75*501802e2SMichael Riesch 	vb->sequence = stream->frame_idx;
76*501802e2SMichael Riesch 	vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE);
77*501802e2SMichael Riesch 	stream->frame_idx++;
78*501802e2SMichael Riesch }
79*501802e2SMichael Riesch 
80*501802e2SMichael Riesch void rkcif_stream_pingpong(struct rkcif_stream *stream)
81*501802e2SMichael Riesch {
82*501802e2SMichael Riesch 	struct rkcif_buffer *buffer;
83*501802e2SMichael Riesch 
84*501802e2SMichael Riesch 	buffer = stream->buffers[stream->frame_phase];
85*501802e2SMichael Riesch 	if (!buffer->is_dummy)
86*501802e2SMichael Riesch 		rkcif_stream_complete_buffer(stream, buffer);
87*501802e2SMichael Riesch 
88*501802e2SMichael Riesch 	buffer = rkcif_stream_pop_buffer(stream);
89*501802e2SMichael Riesch 	if (buffer) {
90*501802e2SMichael Riesch 		stream->buffers[stream->frame_phase] = buffer;
91*501802e2SMichael Riesch 		stream->buffers[stream->frame_phase]->is_dummy = false;
92*501802e2SMichael Riesch 	} else {
93*501802e2SMichael Riesch 		stream->buffers[stream->frame_phase] = &stream->dummy.buffer;
94*501802e2SMichael Riesch 		stream->buffers[stream->frame_phase]->is_dummy = true;
95*501802e2SMichael Riesch 		dev_dbg(stream->rkcif->dev,
96*501802e2SMichael Riesch 			"no buffer available, frame will be dropped\n");
97*501802e2SMichael Riesch 	}
98*501802e2SMichael Riesch 
99*501802e2SMichael Riesch 	if (stream->queue_buffer)
100*501802e2SMichael Riesch 		stream->queue_buffer(stream, stream->frame_phase);
101*501802e2SMichael Riesch 
102*501802e2SMichael Riesch 	stream->frame_phase = 1 - stream->frame_phase;
103*501802e2SMichael Riesch }
104*501802e2SMichael Riesch 
105*501802e2SMichael Riesch static int rkcif_stream_init_buffers(struct rkcif_stream *stream)
106*501802e2SMichael Riesch {
107*501802e2SMichael Riesch 	struct v4l2_pix_format_mplane *pix = &stream->pix;
108*501802e2SMichael Riesch 
109*501802e2SMichael Riesch 	stream->buffers[0] = rkcif_stream_pop_buffer(stream);
110*501802e2SMichael Riesch 	if (!stream->buffers[0])
111*501802e2SMichael Riesch 		goto err_buff_0;
112*501802e2SMichael Riesch 
113*501802e2SMichael Riesch 	stream->buffers[1] = rkcif_stream_pop_buffer(stream);
114*501802e2SMichael Riesch 	if (!stream->buffers[1])
115*501802e2SMichael Riesch 		goto err_buff_1;
116*501802e2SMichael Riesch 
117*501802e2SMichael Riesch 	if (stream->queue_buffer) {
118*501802e2SMichael Riesch 		stream->queue_buffer(stream, 0);
119*501802e2SMichael Riesch 		stream->queue_buffer(stream, 1);
120*501802e2SMichael Riesch 	}
121*501802e2SMichael Riesch 
122*501802e2SMichael Riesch 	stream->dummy.size = pix->num_planes * pix->plane_fmt[0].sizeimage;
123*501802e2SMichael Riesch 	stream->dummy.vaddr =
124*501802e2SMichael Riesch 		dma_alloc_attrs(stream->rkcif->dev, stream->dummy.size,
125*501802e2SMichael Riesch 				&stream->dummy.buffer.buff_addr[0], GFP_KERNEL,
126*501802e2SMichael Riesch 				DMA_ATTR_NO_KERNEL_MAPPING);
127*501802e2SMichael Riesch 	if (!stream->dummy.vaddr)
128*501802e2SMichael Riesch 		goto err_dummy;
129*501802e2SMichael Riesch 
130*501802e2SMichael Riesch 	for (unsigned int i = 1; i < pix->num_planes; i++)
131*501802e2SMichael Riesch 		stream->dummy.buffer.buff_addr[i] =
132*501802e2SMichael Riesch 			stream->dummy.buffer.buff_addr[i - 1] +
133*501802e2SMichael Riesch 			pix->plane_fmt[i - 1].bytesperline * pix->height;
134*501802e2SMichael Riesch 
135*501802e2SMichael Riesch 	return 0;
136*501802e2SMichael Riesch 
137*501802e2SMichael Riesch err_dummy:
138*501802e2SMichael Riesch 	rkcif_stream_return_buffer(stream->buffers[1], VB2_BUF_STATE_QUEUED);
139*501802e2SMichael Riesch 	stream->buffers[1] = NULL;
140*501802e2SMichael Riesch 
141*501802e2SMichael Riesch err_buff_1:
142*501802e2SMichael Riesch 	rkcif_stream_return_buffer(stream->buffers[0], VB2_BUF_STATE_QUEUED);
143*501802e2SMichael Riesch 	stream->buffers[0] = NULL;
144*501802e2SMichael Riesch err_buff_0:
145*501802e2SMichael Riesch 	return -EINVAL;
146*501802e2SMichael Riesch }
147*501802e2SMichael Riesch 
148*501802e2SMichael Riesch static void rkcif_stream_return_all_buffers(struct rkcif_stream *stream,
149*501802e2SMichael Riesch 					    enum vb2_buffer_state state)
150*501802e2SMichael Riesch {
151*501802e2SMichael Riesch 	struct rkcif_buffer *buffer;
152*501802e2SMichael Riesch 
153*501802e2SMichael Riesch 	if (stream->buffers[0] && !stream->buffers[0]->is_dummy) {
154*501802e2SMichael Riesch 		rkcif_stream_return_buffer(stream->buffers[0], state);
155*501802e2SMichael Riesch 		stream->buffers[0] = NULL;
156*501802e2SMichael Riesch 	}
157*501802e2SMichael Riesch 
158*501802e2SMichael Riesch 	if (stream->buffers[1] && !stream->buffers[1]->is_dummy) {
159*501802e2SMichael Riesch 		rkcif_stream_return_buffer(stream->buffers[1], state);
160*501802e2SMichael Riesch 		stream->buffers[1] = NULL;
161*501802e2SMichael Riesch 	}
162*501802e2SMichael Riesch 
163*501802e2SMichael Riesch 	while ((buffer = rkcif_stream_pop_buffer(stream)))
164*501802e2SMichael Riesch 		rkcif_stream_return_buffer(buffer, state);
165*501802e2SMichael Riesch 
166*501802e2SMichael Riesch 	if (stream->dummy.vaddr) {
167*501802e2SMichael Riesch 		dma_free_attrs(stream->rkcif->dev, stream->dummy.size,
168*501802e2SMichael Riesch 			       stream->dummy.vaddr,
169*501802e2SMichael Riesch 			       stream->dummy.buffer.buff_addr[0],
170*501802e2SMichael Riesch 			       DMA_ATTR_NO_KERNEL_MAPPING);
171*501802e2SMichael Riesch 		stream->dummy.vaddr = NULL;
172*501802e2SMichael Riesch 	}
173*501802e2SMichael Riesch }
174*501802e2SMichael Riesch 
175*501802e2SMichael Riesch static int rkcif_stream_setup_queue(struct vb2_queue *queue,
176*501802e2SMichael Riesch 				    unsigned int *num_buffers,
177*501802e2SMichael Riesch 				    unsigned int *num_planes,
178*501802e2SMichael Riesch 				    unsigned int sizes[],
179*501802e2SMichael Riesch 				    struct device *alloc_devs[])
180*501802e2SMichael Riesch {
181*501802e2SMichael Riesch 	struct rkcif_stream *stream = queue->drv_priv;
182*501802e2SMichael Riesch 	struct v4l2_pix_format_mplane *pix = &stream->pix;
183*501802e2SMichael Riesch 
184*501802e2SMichael Riesch 	if (*num_planes) {
185*501802e2SMichael Riesch 		if (*num_planes != pix->num_planes)
186*501802e2SMichael Riesch 			return -EINVAL;
187*501802e2SMichael Riesch 
188*501802e2SMichael Riesch 		for (unsigned int i = 0; i < pix->num_planes; i++)
189*501802e2SMichael Riesch 			if (sizes[i] < pix->plane_fmt[i].sizeimage)
190*501802e2SMichael Riesch 				return -EINVAL;
191*501802e2SMichael Riesch 	} else {
192*501802e2SMichael Riesch 		*num_planes = pix->num_planes;
193*501802e2SMichael Riesch 		for (unsigned int i = 0; i < pix->num_planes; i++)
194*501802e2SMichael Riesch 			sizes[i] = pix->plane_fmt[i].sizeimage;
195*501802e2SMichael Riesch 	}
196*501802e2SMichael Riesch 
197*501802e2SMichael Riesch 	return 0;
198*501802e2SMichael Riesch }
199*501802e2SMichael Riesch 
200*501802e2SMichael Riesch static int rkcif_stream_prepare_buffer(struct vb2_buffer *vb)
201*501802e2SMichael Riesch {
202*501802e2SMichael Riesch 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
203*501802e2SMichael Riesch 	struct rkcif_buffer *buffer = to_rkcif_buffer(vbuf);
204*501802e2SMichael Riesch 	struct rkcif_stream *stream = vb->vb2_queue->drv_priv;
205*501802e2SMichael Riesch 	const struct rkcif_output_fmt *fmt;
206*501802e2SMichael Riesch 	struct v4l2_pix_format_mplane *pix = &stream->pix;
207*501802e2SMichael Riesch 	unsigned int i;
208*501802e2SMichael Riesch 
209*501802e2SMichael Riesch 	memset(buffer->buff_addr, 0, sizeof(buffer->buff_addr));
210*501802e2SMichael Riesch 	for (i = 0; i < pix->num_planes; i++)
211*501802e2SMichael Riesch 		buffer->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
212*501802e2SMichael Riesch 
213*501802e2SMichael Riesch 	/* apply fallback for non-mplane formats, if required */
214*501802e2SMichael Riesch 	if (pix->num_planes == 1) {
215*501802e2SMichael Riesch 		fmt = rkcif_stream_find_output_fmt(stream, true,
216*501802e2SMichael Riesch 						   pix->pixelformat);
217*501802e2SMichael Riesch 		for (i = 1; i < fmt->cplanes; i++)
218*501802e2SMichael Riesch 			buffer->buff_addr[i] =
219*501802e2SMichael Riesch 				buffer->buff_addr[i - 1] +
220*501802e2SMichael Riesch 				pix->plane_fmt[i - 1].bytesperline *
221*501802e2SMichael Riesch 					pix->height;
222*501802e2SMichael Riesch 	}
223*501802e2SMichael Riesch 
224*501802e2SMichael Riesch 	for (i = 0; i < pix->num_planes; i++) {
225*501802e2SMichael Riesch 		unsigned long size = pix->plane_fmt[i].sizeimage;
226*501802e2SMichael Riesch 
227*501802e2SMichael Riesch 		if (vb2_plane_size(vb, i) < size) {
228*501802e2SMichael Riesch 			dev_err(stream->rkcif->dev,
229*501802e2SMichael Riesch 				"user buffer too small (%ld < %ld)\n",
230*501802e2SMichael Riesch 				vb2_plane_size(vb, i), size);
231*501802e2SMichael Riesch 			return -EINVAL;
232*501802e2SMichael Riesch 		}
233*501802e2SMichael Riesch 
234*501802e2SMichael Riesch 		vb2_set_plane_payload(vb, i, size);
235*501802e2SMichael Riesch 	}
236*501802e2SMichael Riesch 
237*501802e2SMichael Riesch 	vbuf->field = V4L2_FIELD_NONE;
238*501802e2SMichael Riesch 
239*501802e2SMichael Riesch 	return 0;
240*501802e2SMichael Riesch }
241*501802e2SMichael Riesch 
242*501802e2SMichael Riesch static void rkcif_stream_queue_buffer(struct vb2_buffer *vb)
243*501802e2SMichael Riesch {
244*501802e2SMichael Riesch 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
245*501802e2SMichael Riesch 	struct rkcif_buffer *buffer = to_rkcif_buffer(vbuf);
246*501802e2SMichael Riesch 	struct rkcif_stream *stream = vb->vb2_queue->drv_priv;
247*501802e2SMichael Riesch 
248*501802e2SMichael Riesch 	rkcif_stream_push_buffer(stream, buffer);
249*501802e2SMichael Riesch }
250*501802e2SMichael Riesch 
251*501802e2SMichael Riesch static int rkcif_stream_start_streaming(struct vb2_queue *queue,
252*501802e2SMichael Riesch 					unsigned int count)
253*501802e2SMichael Riesch {
254*501802e2SMichael Riesch 	struct rkcif_stream *stream = queue->drv_priv;
255*501802e2SMichael Riesch 	struct rkcif_device *rkcif = stream->rkcif;
256*501802e2SMichael Riesch 	u64 mask;
257*501802e2SMichael Riesch 	int ret;
258*501802e2SMichael Riesch 
259*501802e2SMichael Riesch 	stream->frame_idx = 0;
260*501802e2SMichael Riesch 	stream->frame_phase = 0;
261*501802e2SMichael Riesch 
262*501802e2SMichael Riesch 	ret = video_device_pipeline_start(&stream->vdev, &stream->pipeline);
263*501802e2SMichael Riesch 	if (ret) {
264*501802e2SMichael Riesch 		dev_err(rkcif->dev, "failed to start pipeline %d\n", ret);
265*501802e2SMichael Riesch 		goto err_out;
266*501802e2SMichael Riesch 	}
267*501802e2SMichael Riesch 
268*501802e2SMichael Riesch 	ret = pm_runtime_resume_and_get(rkcif->dev);
269*501802e2SMichael Riesch 	if (ret < 0) {
270*501802e2SMichael Riesch 		dev_err(rkcif->dev, "failed to get runtime pm, %d\n", ret);
271*501802e2SMichael Riesch 		goto err_pipeline_stop;
272*501802e2SMichael Riesch 	}
273*501802e2SMichael Riesch 
274*501802e2SMichael Riesch 	ret = rkcif_stream_init_buffers(stream);
275*501802e2SMichael Riesch 	if (ret)
276*501802e2SMichael Riesch 		goto err_runtime_put;
277*501802e2SMichael Riesch 
278*501802e2SMichael Riesch 	if (stream->start_streaming) {
279*501802e2SMichael Riesch 		ret = stream->start_streaming(stream);
280*501802e2SMichael Riesch 		if (ret < 0)
281*501802e2SMichael Riesch 			goto err_runtime_put;
282*501802e2SMichael Riesch 	}
283*501802e2SMichael Riesch 
284*501802e2SMichael Riesch 	mask = BIT_ULL(stream->id);
285*501802e2SMichael Riesch 	ret = v4l2_subdev_enable_streams(&stream->interface->sd,
286*501802e2SMichael Riesch 					 RKCIF_IF_PAD_SRC, mask);
287*501802e2SMichael Riesch 	if (ret < 0)
288*501802e2SMichael Riesch 		goto err_stop_stream;
289*501802e2SMichael Riesch 
290*501802e2SMichael Riesch 	return 0;
291*501802e2SMichael Riesch 
292*501802e2SMichael Riesch err_stop_stream:
293*501802e2SMichael Riesch 	if (stream->stop_streaming)
294*501802e2SMichael Riesch 		stream->stop_streaming(stream);
295*501802e2SMichael Riesch err_runtime_put:
296*501802e2SMichael Riesch 	pm_runtime_put(rkcif->dev);
297*501802e2SMichael Riesch err_pipeline_stop:
298*501802e2SMichael Riesch 	video_device_pipeline_stop(&stream->vdev);
299*501802e2SMichael Riesch err_out:
300*501802e2SMichael Riesch 	rkcif_stream_return_all_buffers(stream, VB2_BUF_STATE_QUEUED);
301*501802e2SMichael Riesch 	return ret;
302*501802e2SMichael Riesch }
303*501802e2SMichael Riesch 
304*501802e2SMichael Riesch static void rkcif_stream_stop_streaming(struct vb2_queue *queue)
305*501802e2SMichael Riesch {
306*501802e2SMichael Riesch 	struct rkcif_stream *stream = queue->drv_priv;
307*501802e2SMichael Riesch 	struct rkcif_device *rkcif = stream->rkcif;
308*501802e2SMichael Riesch 	u64 mask;
309*501802e2SMichael Riesch 	int ret;
310*501802e2SMichael Riesch 
311*501802e2SMichael Riesch 	mask = BIT_ULL(stream->id);
312*501802e2SMichael Riesch 	v4l2_subdev_disable_streams(&stream->interface->sd, RKCIF_IF_PAD_SRC,
313*501802e2SMichael Riesch 				    mask);
314*501802e2SMichael Riesch 
315*501802e2SMichael Riesch 	stream->stopping = true;
316*501802e2SMichael Riesch 	ret = wait_event_timeout(stream->wq_stopped, !stream->stopping,
317*501802e2SMichael Riesch 				 msecs_to_jiffies(1000));
318*501802e2SMichael Riesch 
319*501802e2SMichael Riesch 	if (!ret && stream->stop_streaming)
320*501802e2SMichael Riesch 		stream->stop_streaming(stream);
321*501802e2SMichael Riesch 
322*501802e2SMichael Riesch 	pm_runtime_put(rkcif->dev);
323*501802e2SMichael Riesch 
324*501802e2SMichael Riesch 	rkcif_stream_return_all_buffers(stream, VB2_BUF_STATE_ERROR);
325*501802e2SMichael Riesch 
326*501802e2SMichael Riesch 	video_device_pipeline_stop(&stream->vdev);
327*501802e2SMichael Riesch }
328*501802e2SMichael Riesch 
329*501802e2SMichael Riesch static const struct vb2_ops rkcif_stream_vb2_ops = {
330*501802e2SMichael Riesch 	.queue_setup = rkcif_stream_setup_queue,
331*501802e2SMichael Riesch 	.buf_prepare = rkcif_stream_prepare_buffer,
332*501802e2SMichael Riesch 	.buf_queue = rkcif_stream_queue_buffer,
333*501802e2SMichael Riesch 	.start_streaming = rkcif_stream_start_streaming,
334*501802e2SMichael Riesch 	.stop_streaming = rkcif_stream_stop_streaming,
335*501802e2SMichael Riesch };
336*501802e2SMichael Riesch 
337*501802e2SMichael Riesch static int rkcif_stream_fill_format(struct rkcif_stream *stream,
338*501802e2SMichael Riesch 				    struct v4l2_pix_format_mplane *pix)
339*501802e2SMichael Riesch {
340*501802e2SMichael Riesch 	const struct rkcif_output_fmt *fmt;
341*501802e2SMichael Riesch 	u32 height, width;
342*501802e2SMichael Riesch 	int ret;
343*501802e2SMichael Riesch 
344*501802e2SMichael Riesch 	fmt = rkcif_stream_find_output_fmt(stream, true, pix->pixelformat);
345*501802e2SMichael Riesch 	height = clamp_t(u32, pix->height, CIF_MIN_HEIGHT, CIF_MAX_HEIGHT);
346*501802e2SMichael Riesch 	width = clamp_t(u32, pix->width, CIF_MIN_WIDTH, CIF_MAX_WIDTH);
347*501802e2SMichael Riesch 	ret = v4l2_fill_pixfmt_mp(pix, fmt->fourcc, width, height);
348*501802e2SMichael Riesch 	if (ret)
349*501802e2SMichael Riesch 		return ret;
350*501802e2SMichael Riesch 
351*501802e2SMichael Riesch 	pix->field = V4L2_FIELD_NONE;
352*501802e2SMichael Riesch 
353*501802e2SMichael Riesch 	return 0;
354*501802e2SMichael Riesch }
355*501802e2SMichael Riesch 
356*501802e2SMichael Riesch static int rkcif_stream_try_format(struct file *file, void *fh,
357*501802e2SMichael Riesch 				   struct v4l2_format *f)
358*501802e2SMichael Riesch {
359*501802e2SMichael Riesch 	struct rkcif_stream *stream = video_drvdata(file);
360*501802e2SMichael Riesch 	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
361*501802e2SMichael Riesch 
362*501802e2SMichael Riesch 	return rkcif_stream_fill_format(stream, pix);
363*501802e2SMichael Riesch }
364*501802e2SMichael Riesch 
365*501802e2SMichael Riesch static int rkcif_stream_set_format(struct file *file, void *priv,
366*501802e2SMichael Riesch 				   struct v4l2_format *f)
367*501802e2SMichael Riesch {
368*501802e2SMichael Riesch 	struct rkcif_stream *stream = video_drvdata(file);
369*501802e2SMichael Riesch 	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
370*501802e2SMichael Riesch 	int ret;
371*501802e2SMichael Riesch 
372*501802e2SMichael Riesch 	if (vb2_is_busy(&stream->buf_queue))
373*501802e2SMichael Riesch 		return -EBUSY;
374*501802e2SMichael Riesch 
375*501802e2SMichael Riesch 	ret = rkcif_stream_try_format(file, priv, f);
376*501802e2SMichael Riesch 	if (ret)
377*501802e2SMichael Riesch 		return ret;
378*501802e2SMichael Riesch 
379*501802e2SMichael Riesch 	stream->pix = *pix;
380*501802e2SMichael Riesch 
381*501802e2SMichael Riesch 	return 0;
382*501802e2SMichael Riesch }
383*501802e2SMichael Riesch 
384*501802e2SMichael Riesch static int rkcif_stream_get_format(struct file *file, void *fh,
385*501802e2SMichael Riesch 				   struct v4l2_format *f)
386*501802e2SMichael Riesch {
387*501802e2SMichael Riesch 	struct rkcif_stream *stream = video_drvdata(file);
388*501802e2SMichael Riesch 
389*501802e2SMichael Riesch 	f->fmt.pix_mp = stream->pix;
390*501802e2SMichael Riesch 
391*501802e2SMichael Riesch 	return 0;
392*501802e2SMichael Riesch }
393*501802e2SMichael Riesch 
394*501802e2SMichael Riesch static int rkcif_stream_enum_formats(struct file *file, void *priv,
395*501802e2SMichael Riesch 				     struct v4l2_fmtdesc *f)
396*501802e2SMichael Riesch {
397*501802e2SMichael Riesch 	struct rkcif_stream *stream = video_drvdata(file);
398*501802e2SMichael Riesch 
399*501802e2SMichael Riesch 	if (f->index >= stream->out_fmts_num)
400*501802e2SMichael Riesch 		return -EINVAL;
401*501802e2SMichael Riesch 
402*501802e2SMichael Riesch 	f->pixelformat = stream->out_fmts[f->index].fourcc;
403*501802e2SMichael Riesch 
404*501802e2SMichael Riesch 	return 0;
405*501802e2SMichael Riesch }
406*501802e2SMichael Riesch 
407*501802e2SMichael Riesch static int rkcif_stream_enum_framesizes(struct file *file, void *fh,
408*501802e2SMichael Riesch 					struct v4l2_frmsizeenum *fsize)
409*501802e2SMichael Riesch {
410*501802e2SMichael Riesch 	struct rkcif_stream *stream = video_drvdata(file);
411*501802e2SMichael Riesch 
412*501802e2SMichael Riesch 	if (fsize->index > 0)
413*501802e2SMichael Riesch 		return -EINVAL;
414*501802e2SMichael Riesch 
415*501802e2SMichael Riesch 	if (!rkcif_stream_find_output_fmt(stream, false, fsize->pixel_format))
416*501802e2SMichael Riesch 		return -EINVAL;
417*501802e2SMichael Riesch 
418*501802e2SMichael Riesch 	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
419*501802e2SMichael Riesch 	fsize->stepwise.min_width = CIF_MIN_WIDTH;
420*501802e2SMichael Riesch 	fsize->stepwise.max_width = CIF_MAX_WIDTH;
421*501802e2SMichael Riesch 	fsize->stepwise.step_width = 8;
422*501802e2SMichael Riesch 	fsize->stepwise.min_height = CIF_MIN_HEIGHT;
423*501802e2SMichael Riesch 	fsize->stepwise.max_height = CIF_MAX_HEIGHT;
424*501802e2SMichael Riesch 	fsize->stepwise.step_height = 8;
425*501802e2SMichael Riesch 
426*501802e2SMichael Riesch 	return 0;
427*501802e2SMichael Riesch }
428*501802e2SMichael Riesch 
429*501802e2SMichael Riesch static int rkcif_stream_querycap(struct file *file, void *priv,
430*501802e2SMichael Riesch 				 struct v4l2_capability *cap)
431*501802e2SMichael Riesch {
432*501802e2SMichael Riesch 	struct rkcif_stream *stream = video_drvdata(file);
433*501802e2SMichael Riesch 	struct device *dev = stream->rkcif->dev;
434*501802e2SMichael Riesch 
435*501802e2SMichael Riesch 	strscpy(cap->driver, dev->driver->name, sizeof(cap->driver));
436*501802e2SMichael Riesch 	strscpy(cap->card, dev->driver->name, sizeof(cap->card));
437*501802e2SMichael Riesch 
438*501802e2SMichael Riesch 	return 0;
439*501802e2SMichael Riesch }
440*501802e2SMichael Riesch 
441*501802e2SMichael Riesch static const struct v4l2_ioctl_ops rkcif_stream_ioctl_ops = {
442*501802e2SMichael Riesch 	.vidioc_reqbufs = vb2_ioctl_reqbufs,
443*501802e2SMichael Riesch 	.vidioc_querybuf = vb2_ioctl_querybuf,
444*501802e2SMichael Riesch 	.vidioc_create_bufs = vb2_ioctl_create_bufs,
445*501802e2SMichael Riesch 	.vidioc_qbuf = vb2_ioctl_qbuf,
446*501802e2SMichael Riesch 	.vidioc_expbuf = vb2_ioctl_expbuf,
447*501802e2SMichael Riesch 	.vidioc_dqbuf = vb2_ioctl_dqbuf,
448*501802e2SMichael Riesch 	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
449*501802e2SMichael Riesch 	.vidioc_streamon = vb2_ioctl_streamon,
450*501802e2SMichael Riesch 	.vidioc_streamoff = vb2_ioctl_streamoff,
451*501802e2SMichael Riesch 	.vidioc_try_fmt_vid_cap_mplane = rkcif_stream_try_format,
452*501802e2SMichael Riesch 	.vidioc_s_fmt_vid_cap_mplane = rkcif_stream_set_format,
453*501802e2SMichael Riesch 	.vidioc_g_fmt_vid_cap_mplane = rkcif_stream_get_format,
454*501802e2SMichael Riesch 	.vidioc_enum_fmt_vid_cap = rkcif_stream_enum_formats,
455*501802e2SMichael Riesch 	.vidioc_enum_framesizes = rkcif_stream_enum_framesizes,
456*501802e2SMichael Riesch 	.vidioc_querycap = rkcif_stream_querycap,
457*501802e2SMichael Riesch };
458*501802e2SMichael Riesch 
459*501802e2SMichael Riesch static int rkcif_stream_link_validate(struct media_link *link)
460*501802e2SMichael Riesch {
461*501802e2SMichael Riesch 	struct video_device *vdev =
462*501802e2SMichael Riesch 		media_entity_to_video_device(link->sink->entity);
463*501802e2SMichael Riesch 	struct v4l2_mbus_framefmt *source_fmt;
464*501802e2SMichael Riesch 	struct v4l2_subdev *sd;
465*501802e2SMichael Riesch 	struct v4l2_subdev_state *state;
466*501802e2SMichael Riesch 	struct rkcif_stream *stream = to_rkcif_stream(vdev);
467*501802e2SMichael Riesch 	int ret = -EINVAL;
468*501802e2SMichael Riesch 
469*501802e2SMichael Riesch 	if (!media_entity_remote_source_pad_unique(link->sink->entity))
470*501802e2SMichael Riesch 		return -ENOTCONN;
471*501802e2SMichael Riesch 
472*501802e2SMichael Riesch 	sd = media_entity_to_v4l2_subdev(link->source->entity);
473*501802e2SMichael Riesch 
474*501802e2SMichael Riesch 	state = v4l2_subdev_lock_and_get_active_state(sd);
475*501802e2SMichael Riesch 
476*501802e2SMichael Riesch 	source_fmt = v4l2_subdev_state_get_format(state, link->source->index,
477*501802e2SMichael Riesch 						  stream->id);
478*501802e2SMichael Riesch 	if (!source_fmt)
479*501802e2SMichael Riesch 		goto out;
480*501802e2SMichael Riesch 
481*501802e2SMichael Riesch 	if (source_fmt->height != stream->pix.height ||
482*501802e2SMichael Riesch 	    source_fmt->width != stream->pix.width) {
483*501802e2SMichael Riesch 		dev_dbg(stream->rkcif->dev,
484*501802e2SMichael Riesch 			"link '%s':%u -> '%s':%u not valid: %ux%u != %ux%u\n",
485*501802e2SMichael Riesch 			link->source->entity->name, link->source->index,
486*501802e2SMichael Riesch 			link->sink->entity->name, link->sink->index,
487*501802e2SMichael Riesch 			source_fmt->width, source_fmt->height,
488*501802e2SMichael Riesch 			stream->pix.width, stream->pix.height);
489*501802e2SMichael Riesch 		goto out;
490*501802e2SMichael Riesch 	}
491*501802e2SMichael Riesch 
492*501802e2SMichael Riesch 	ret = 0;
493*501802e2SMichael Riesch 
494*501802e2SMichael Riesch out:
495*501802e2SMichael Riesch 	v4l2_subdev_unlock_state(state);
496*501802e2SMichael Riesch 	return ret;
497*501802e2SMichael Riesch }
498*501802e2SMichael Riesch 
499*501802e2SMichael Riesch static const struct media_entity_operations rkcif_stream_media_ops = {
500*501802e2SMichael Riesch 	.link_validate = rkcif_stream_link_validate,
501*501802e2SMichael Riesch };
502*501802e2SMichael Riesch 
503*501802e2SMichael Riesch static const struct v4l2_file_operations rkcif_stream_file_ops = {
504*501802e2SMichael Riesch 	.open = v4l2_fh_open,
505*501802e2SMichael Riesch 	.release = vb2_fop_release,
506*501802e2SMichael Riesch 	.unlocked_ioctl = video_ioctl2,
507*501802e2SMichael Riesch 	.poll = vb2_fop_poll,
508*501802e2SMichael Riesch 	.mmap = vb2_fop_mmap,
509*501802e2SMichael Riesch };
510*501802e2SMichael Riesch 
511*501802e2SMichael Riesch static int rkcif_stream_init_vb2_queue(struct vb2_queue *q,
512*501802e2SMichael Riesch 				       struct rkcif_stream *stream)
513*501802e2SMichael Riesch {
514*501802e2SMichael Riesch 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
515*501802e2SMichael Riesch 	q->io_modes = VB2_MMAP | VB2_DMABUF;
516*501802e2SMichael Riesch 	q->drv_priv = stream;
517*501802e2SMichael Riesch 	q->ops = &rkcif_stream_vb2_ops;
518*501802e2SMichael Riesch 	q->mem_ops = &vb2_dma_contig_memops;
519*501802e2SMichael Riesch 	q->buf_struct_size = sizeof(struct rkcif_buffer);
520*501802e2SMichael Riesch 	q->min_queued_buffers = CIF_REQ_BUFS_MIN;
521*501802e2SMichael Riesch 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
522*501802e2SMichael Riesch 	q->lock = &stream->vlock;
523*501802e2SMichael Riesch 	q->dev = stream->rkcif->dev;
524*501802e2SMichael Riesch 
525*501802e2SMichael Riesch 	return vb2_queue_init(q);
526*501802e2SMichael Riesch }
527*501802e2SMichael Riesch 
528*501802e2SMichael Riesch int rkcif_stream_register(struct rkcif_device *rkcif,
529*501802e2SMichael Riesch 			  struct rkcif_stream *stream)
530*501802e2SMichael Riesch {
531*501802e2SMichael Riesch 	struct rkcif_interface *interface = stream->interface;
532*501802e2SMichael Riesch 	struct v4l2_device *v4l2_dev = &rkcif->v4l2_dev;
533*501802e2SMichael Riesch 	struct video_device *vdev = &stream->vdev;
534*501802e2SMichael Riesch 	u32 link_flags = 0;
535*501802e2SMichael Riesch 	int ret;
536*501802e2SMichael Riesch 
537*501802e2SMichael Riesch 	stream->rkcif = rkcif;
538*501802e2SMichael Riesch 
539*501802e2SMichael Riesch 	INIT_LIST_HEAD(&stream->driver_queue);
540*501802e2SMichael Riesch 	spin_lock_init(&stream->driver_queue_lock);
541*501802e2SMichael Riesch 
542*501802e2SMichael Riesch 	init_waitqueue_head(&stream->wq_stopped);
543*501802e2SMichael Riesch 
544*501802e2SMichael Riesch 	mutex_init(&stream->vlock);
545*501802e2SMichael Riesch 
546*501802e2SMichael Riesch 	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING |
547*501802e2SMichael Riesch 			    V4L2_CAP_IO_MC;
548*501802e2SMichael Riesch 	vdev->entity.ops = &rkcif_stream_media_ops;
549*501802e2SMichael Riesch 	vdev->fops = &rkcif_stream_file_ops;
550*501802e2SMichael Riesch 	vdev->ioctl_ops = &rkcif_stream_ioctl_ops;
551*501802e2SMichael Riesch 	vdev->lock = &stream->vlock;
552*501802e2SMichael Riesch 	vdev->minor = -1;
553*501802e2SMichael Riesch 	vdev->release = video_device_release_empty;
554*501802e2SMichael Riesch 	vdev->v4l2_dev = v4l2_dev;
555*501802e2SMichael Riesch 	vdev->vfl_dir = VFL_DIR_RX;
556*501802e2SMichael Riesch 	video_set_drvdata(vdev, stream);
557*501802e2SMichael Riesch 
558*501802e2SMichael Riesch 	stream->pad.flags = MEDIA_PAD_FL_SINK;
559*501802e2SMichael Riesch 
560*501802e2SMichael Riesch 	stream->pix.height = CIF_MIN_HEIGHT;
561*501802e2SMichael Riesch 	stream->pix.width = CIF_MIN_WIDTH;
562*501802e2SMichael Riesch 	rkcif_stream_fill_format(stream, &stream->pix);
563*501802e2SMichael Riesch 
564*501802e2SMichael Riesch 	rkcif_stream_init_vb2_queue(&stream->buf_queue, stream);
565*501802e2SMichael Riesch 
566*501802e2SMichael Riesch 	vdev->queue = &stream->buf_queue;
567*501802e2SMichael Riesch 	if (interface->type == RKCIF_IF_DVP)
568*501802e2SMichael Riesch 		snprintf(vdev->name, sizeof(vdev->name), "rkcif-dvp0-id%d",
569*501802e2SMichael Riesch 			 stream->id);
570*501802e2SMichael Riesch 	else if (interface->type == RKCIF_IF_MIPI)
571*501802e2SMichael Riesch 		snprintf(vdev->name, sizeof(vdev->name), "rkcif-mipi%d-id%d",
572*501802e2SMichael Riesch 			 interface->index - RKCIF_MIPI_BASE, stream->id);
573*501802e2SMichael Riesch 
574*501802e2SMichael Riesch 	ret = media_entity_pads_init(&vdev->entity, 1, &stream->pad);
575*501802e2SMichael Riesch 	if (ret < 0) {
576*501802e2SMichael Riesch 		dev_err(rkcif->dev,
577*501802e2SMichael Riesch 			"failed to initialize stream media pad: %d\n", ret);
578*501802e2SMichael Riesch 		return ret;
579*501802e2SMichael Riesch 	}
580*501802e2SMichael Riesch 
581*501802e2SMichael Riesch 	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
582*501802e2SMichael Riesch 	if (ret < 0) {
583*501802e2SMichael Riesch 		dev_err(rkcif->dev, "failed to register video device: %d\n",
584*501802e2SMichael Riesch 			ret);
585*501802e2SMichael Riesch 		goto err_media_entity_cleanup;
586*501802e2SMichael Riesch 	}
587*501802e2SMichael Riesch 
588*501802e2SMichael Riesch 	/* enable only stream ID0 by default */
589*501802e2SMichael Riesch 	if (stream->id == RKCIF_ID0)
590*501802e2SMichael Riesch 		link_flags |= MEDIA_LNK_FL_ENABLED;
591*501802e2SMichael Riesch 
592*501802e2SMichael Riesch 	ret = media_create_pad_link(&interface->sd.entity, RKCIF_IF_PAD_SRC,
593*501802e2SMichael Riesch 				    &stream->vdev.entity, 0, link_flags);
594*501802e2SMichael Riesch 	if (ret) {
595*501802e2SMichael Riesch 		dev_err(rkcif->dev, "failed to link stream media pad: %d\n",
596*501802e2SMichael Riesch 			ret);
597*501802e2SMichael Riesch 		goto err_video_unregister;
598*501802e2SMichael Riesch 	}
599*501802e2SMichael Riesch 
600*501802e2SMichael Riesch 	v4l2_info(v4l2_dev, "registered %s as /dev/video%d\n", vdev->name,
601*501802e2SMichael Riesch 		  vdev->num);
602*501802e2SMichael Riesch 
603*501802e2SMichael Riesch 	return 0;
604*501802e2SMichael Riesch 
605*501802e2SMichael Riesch err_video_unregister:
606*501802e2SMichael Riesch 	video_unregister_device(&stream->vdev);
607*501802e2SMichael Riesch err_media_entity_cleanup:
608*501802e2SMichael Riesch 	media_entity_cleanup(&stream->vdev.entity);
609*501802e2SMichael Riesch 	return ret;
610*501802e2SMichael Riesch }
611*501802e2SMichael Riesch 
612*501802e2SMichael Riesch void rkcif_stream_unregister(struct rkcif_stream *stream)
613*501802e2SMichael Riesch {
614*501802e2SMichael Riesch 	video_unregister_device(&stream->vdev);
615*501802e2SMichael Riesch 	media_entity_cleanup(&stream->vdev.entity);
616*501802e2SMichael Riesch }
617*501802e2SMichael Riesch 
618*501802e2SMichael Riesch const struct rkcif_output_fmt *
619*501802e2SMichael Riesch rkcif_stream_find_output_fmt(struct rkcif_stream *stream, bool ret_def,
620*501802e2SMichael Riesch 			     u32 pixelfmt)
621*501802e2SMichael Riesch {
622*501802e2SMichael Riesch 	const struct rkcif_output_fmt *fmt;
623*501802e2SMichael Riesch 
624*501802e2SMichael Riesch 	WARN_ON(stream->out_fmts_num == 0);
625*501802e2SMichael Riesch 
626*501802e2SMichael Riesch 	for (unsigned int i = 0; i < stream->out_fmts_num; i++) {
627*501802e2SMichael Riesch 		fmt = &stream->out_fmts[i];
628*501802e2SMichael Riesch 		if (fmt->fourcc == pixelfmt)
629*501802e2SMichael Riesch 			return fmt;
630*501802e2SMichael Riesch 	}
631*501802e2SMichael Riesch 
632*501802e2SMichael Riesch 	if (ret_def)
633*501802e2SMichael Riesch 		return &stream->out_fmts[0];
634*501802e2SMichael Riesch 	else
635*501802e2SMichael Riesch 		return NULL;
636*501802e2SMichael Riesch }
637