1633b388fSRobert Foss // SPDX-License-Identifier: GPL-2.0
2633b388fSRobert Foss /*
3633b388fSRobert Foss  * camss-vfe-gen1.c
4633b388fSRobert Foss  *
5633b388fSRobert Foss  * Qualcomm MSM Camera Subsystem - VFE Common functionality for Gen 1 versions of hw (4.1, 4.7..)
6633b388fSRobert Foss  *
7633b388fSRobert Foss  * Copyright (C) 2020 Linaro Ltd.
8633b388fSRobert Foss  */
9633b388fSRobert Foss 
10633b388fSRobert Foss #include "camss.h"
11633b388fSRobert Foss #include "camss-vfe.h"
12633b388fSRobert Foss #include "camss-vfe-gen1.h"
13633b388fSRobert Foss 
14633b388fSRobert Foss /* Max number of frame drop updates per frame */
15633b388fSRobert Foss #define VFE_FRAME_DROP_UPDATES 2
16633b388fSRobert Foss #define VFE_NEXT_SOF_MS 500
17633b388fSRobert Foss 
vfe_gen1_halt(struct vfe_device * vfe)18633b388fSRobert Foss int vfe_gen1_halt(struct vfe_device *vfe)
19633b388fSRobert Foss {
20633b388fSRobert Foss 	unsigned long time;
21633b388fSRobert Foss 
22633b388fSRobert Foss 	reinit_completion(&vfe->halt_complete);
23633b388fSRobert Foss 
24633b388fSRobert Foss 	vfe->ops_gen1->halt_request(vfe);
25633b388fSRobert Foss 
26633b388fSRobert Foss 	time = wait_for_completion_timeout(&vfe->halt_complete,
27633b388fSRobert Foss 					   msecs_to_jiffies(VFE_HALT_TIMEOUT_MS));
28633b388fSRobert Foss 	if (!time) {
29633b388fSRobert Foss 		dev_err(vfe->camss->dev, "VFE halt timeout\n");
30633b388fSRobert Foss 		return -EIO;
31633b388fSRobert Foss 	}
32633b388fSRobert Foss 
33633b388fSRobert Foss 	return 0;
34633b388fSRobert Foss }
35633b388fSRobert Foss 
vfe_disable_output(struct vfe_line * line)36633b388fSRobert Foss static int vfe_disable_output(struct vfe_line *line)
37633b388fSRobert Foss {
38633b388fSRobert Foss 	struct vfe_device *vfe = to_vfe(line);
39633b388fSRobert Foss 	struct vfe_output *output = &line->output;
40633b388fSRobert Foss 	const struct vfe_hw_ops *ops = vfe->ops;
41633b388fSRobert Foss 	unsigned long flags;
42633b388fSRobert Foss 	unsigned long time;
43633b388fSRobert Foss 	unsigned int i;
44633b388fSRobert Foss 
45633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
46633b388fSRobert Foss 
47633b388fSRobert Foss 	output->gen1.wait_sof = 1;
48633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
49633b388fSRobert Foss 
50633b388fSRobert Foss 	time = wait_for_completion_timeout(&output->sof, msecs_to_jiffies(VFE_NEXT_SOF_MS));
51633b388fSRobert Foss 	if (!time)
52633b388fSRobert Foss 		dev_err(vfe->camss->dev, "VFE sof timeout\n");
53633b388fSRobert Foss 
54633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
55633b388fSRobert Foss 	for (i = 0; i < output->wm_num; i++)
56633b388fSRobert Foss 		vfe->ops_gen1->wm_enable(vfe, output->wm_idx[i], 0);
57633b388fSRobert Foss 
58633b388fSRobert Foss 	ops->reg_update(vfe, line->id);
59633b388fSRobert Foss 	output->wait_reg_update = 1;
60633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
61633b388fSRobert Foss 
62633b388fSRobert Foss 	time = wait_for_completion_timeout(&output->reg_update, msecs_to_jiffies(VFE_NEXT_SOF_MS));
63633b388fSRobert Foss 	if (!time)
64633b388fSRobert Foss 		dev_err(vfe->camss->dev, "VFE reg update timeout\n");
65633b388fSRobert Foss 
66633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
67633b388fSRobert Foss 
68633b388fSRobert Foss 	if (line->id != VFE_LINE_PIX) {
69633b388fSRobert Foss 		vfe->ops_gen1->wm_frame_based(vfe, output->wm_idx[0], 0);
70633b388fSRobert Foss 		vfe->ops_gen1->bus_disconnect_wm_from_rdi(vfe, output->wm_idx[0], line->id);
71633b388fSRobert Foss 		vfe->ops_gen1->enable_irq_wm_line(vfe, output->wm_idx[0], line->id, 0);
72633b388fSRobert Foss 		vfe->ops_gen1->set_cgc_override(vfe, output->wm_idx[0], 0);
73633b388fSRobert Foss 		spin_unlock_irqrestore(&vfe->output_lock, flags);
74633b388fSRobert Foss 	} else {
75633b388fSRobert Foss 		for (i = 0; i < output->wm_num; i++) {
76633b388fSRobert Foss 			vfe->ops_gen1->wm_line_based(vfe, output->wm_idx[i], NULL, i, 0);
77633b388fSRobert Foss 			vfe->ops_gen1->set_cgc_override(vfe, output->wm_idx[i], 0);
78633b388fSRobert Foss 		}
79633b388fSRobert Foss 
80633b388fSRobert Foss 		vfe->ops_gen1->enable_irq_pix_line(vfe, 0, line->id, 0);
81633b388fSRobert Foss 		vfe->ops_gen1->set_module_cfg(vfe, 0);
82633b388fSRobert Foss 		vfe->ops_gen1->set_realign_cfg(vfe, line, 0);
83633b388fSRobert Foss 		vfe->ops_gen1->set_xbar_cfg(vfe, output, 0);
84633b388fSRobert Foss 		vfe->ops_gen1->set_camif_cmd(vfe, 0);
85633b388fSRobert Foss 
86633b388fSRobert Foss 		spin_unlock_irqrestore(&vfe->output_lock, flags);
87633b388fSRobert Foss 
88633b388fSRobert Foss 		vfe->ops_gen1->camif_wait_for_stop(vfe, vfe->camss->dev);
89633b388fSRobert Foss 	}
90633b388fSRobert Foss 
91633b388fSRobert Foss 	return 0;
92633b388fSRobert Foss }
93633b388fSRobert Foss 
94633b388fSRobert Foss /*
95633b388fSRobert Foss  * vfe_gen1_disable - Disable streaming on VFE line
96633b388fSRobert Foss  * @line: VFE line
97633b388fSRobert Foss  *
98633b388fSRobert Foss  * Return 0 on success or a negative error code otherwise
99633b388fSRobert Foss  */
vfe_gen1_disable(struct vfe_line * line)100633b388fSRobert Foss int vfe_gen1_disable(struct vfe_line *line)
101633b388fSRobert Foss {
102633b388fSRobert Foss 	struct vfe_device *vfe = to_vfe(line);
103633b388fSRobert Foss 
104633b388fSRobert Foss 	vfe_disable_output(line);
105633b388fSRobert Foss 
106633b388fSRobert Foss 	vfe_put_output(line);
107633b388fSRobert Foss 
108633b388fSRobert Foss 	mutex_lock(&vfe->stream_lock);
109633b388fSRobert Foss 
110633b388fSRobert Foss 	if (vfe->stream_count == 1)
111633b388fSRobert Foss 		vfe->ops_gen1->bus_enable_wr_if(vfe, 0);
112633b388fSRobert Foss 
113633b388fSRobert Foss 	vfe->stream_count--;
114633b388fSRobert Foss 
115633b388fSRobert Foss 	mutex_unlock(&vfe->stream_lock);
116633b388fSRobert Foss 
117633b388fSRobert Foss 	return 0;
118633b388fSRobert Foss }
119633b388fSRobert Foss 
vfe_output_init_addrs(struct vfe_device * vfe,struct vfe_output * output,u8 sync,struct vfe_line * line)120633b388fSRobert Foss static void vfe_output_init_addrs(struct vfe_device *vfe,
121633b388fSRobert Foss 				  struct vfe_output *output, u8 sync,
122633b388fSRobert Foss 				  struct vfe_line *line)
123633b388fSRobert Foss {
124633b388fSRobert Foss 	u32 ping_addr;
125633b388fSRobert Foss 	u32 pong_addr;
126633b388fSRobert Foss 	unsigned int i;
127633b388fSRobert Foss 
128633b388fSRobert Foss 	output->gen1.active_buf = 0;
129633b388fSRobert Foss 
130633b388fSRobert Foss 	for (i = 0; i < output->wm_num; i++) {
131633b388fSRobert Foss 		if (output->buf[0])
132633b388fSRobert Foss 			ping_addr = output->buf[0]->addr[i];
133633b388fSRobert Foss 		else
134633b388fSRobert Foss 			ping_addr = 0;
135633b388fSRobert Foss 
136633b388fSRobert Foss 		if (output->buf[1])
137633b388fSRobert Foss 			pong_addr = output->buf[1]->addr[i];
138633b388fSRobert Foss 		else
139633b388fSRobert Foss 			pong_addr = ping_addr;
140633b388fSRobert Foss 
141633b388fSRobert Foss 		vfe->ops_gen1->wm_set_ping_addr(vfe, output->wm_idx[i], ping_addr);
142633b388fSRobert Foss 		vfe->ops_gen1->wm_set_pong_addr(vfe, output->wm_idx[i], pong_addr);
143633b388fSRobert Foss 		if (sync)
144633b388fSRobert Foss 			vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[i]);
145633b388fSRobert Foss 	}
146633b388fSRobert Foss }
147633b388fSRobert Foss 
vfe_output_frame_drop(struct vfe_device * vfe,struct vfe_output * output,u32 drop_pattern)148633b388fSRobert Foss static void vfe_output_frame_drop(struct vfe_device *vfe,
149633b388fSRobert Foss 				  struct vfe_output *output,
150633b388fSRobert Foss 				  u32 drop_pattern)
151633b388fSRobert Foss {
152633b388fSRobert Foss 	u8 drop_period;
153633b388fSRobert Foss 	unsigned int i;
154633b388fSRobert Foss 
155633b388fSRobert Foss 	/* We need to toggle update period to be valid on next frame */
156633b388fSRobert Foss 	output->drop_update_idx++;
157633b388fSRobert Foss 	output->drop_update_idx %= VFE_FRAME_DROP_UPDATES;
158633b388fSRobert Foss 	drop_period = VFE_FRAME_DROP_VAL + output->drop_update_idx;
159633b388fSRobert Foss 
160633b388fSRobert Foss 	for (i = 0; i < output->wm_num; i++) {
161633b388fSRobert Foss 		vfe->ops_gen1->wm_set_framedrop_period(vfe, output->wm_idx[i], drop_period);
162633b388fSRobert Foss 		vfe->ops_gen1->wm_set_framedrop_pattern(vfe, output->wm_idx[i], drop_pattern);
163633b388fSRobert Foss 	}
164633b388fSRobert Foss 
165633b388fSRobert Foss 	vfe->ops->reg_update(vfe, container_of(output, struct vfe_line, output)->id);
166633b388fSRobert Foss }
167633b388fSRobert Foss 
vfe_enable_output(struct vfe_line * line)168633b388fSRobert Foss static int vfe_enable_output(struct vfe_line *line)
169633b388fSRobert Foss {
170633b388fSRobert Foss 	struct vfe_device *vfe = to_vfe(line);
171633b388fSRobert Foss 	struct vfe_output *output = &line->output;
172633b388fSRobert Foss 	const struct vfe_hw_ops *ops = vfe->ops;
173633b388fSRobert Foss 	struct media_entity *sensor;
174633b388fSRobert Foss 	unsigned long flags;
175633b388fSRobert Foss 	unsigned int frame_skip = 0;
176633b388fSRobert Foss 	unsigned int i;
177633b388fSRobert Foss 	u16 ub_size;
178633b388fSRobert Foss 
179633b388fSRobert Foss 	ub_size = vfe->ops_gen1->get_ub_size(vfe->id);
180633b388fSRobert Foss 	if (!ub_size)
181633b388fSRobert Foss 		return -EINVAL;
182633b388fSRobert Foss 
183633b388fSRobert Foss 	sensor = camss_find_sensor(&line->subdev.entity);
184633b388fSRobert Foss 	if (sensor) {
185633b388fSRobert Foss 		struct v4l2_subdev *subdev = media_entity_to_v4l2_subdev(sensor);
186633b388fSRobert Foss 
187633b388fSRobert Foss 		v4l2_subdev_call(subdev, sensor, g_skip_frames, &frame_skip);
188633b388fSRobert Foss 		/* Max frame skip is 29 frames */
189633b388fSRobert Foss 		if (frame_skip > VFE_FRAME_DROP_VAL - 1)
190633b388fSRobert Foss 			frame_skip = VFE_FRAME_DROP_VAL - 1;
191633b388fSRobert Foss 	}
192633b388fSRobert Foss 
193633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
194633b388fSRobert Foss 
195633b388fSRobert Foss 	ops->reg_update_clear(vfe, line->id);
196633b388fSRobert Foss 
197*8ce158c1SMilen Mitkov 	if (output->state > VFE_OUTPUT_RESERVED) {
198633b388fSRobert Foss 		dev_err(vfe->camss->dev, "Output is not in reserved state %d\n", output->state);
199633b388fSRobert Foss 		spin_unlock_irqrestore(&vfe->output_lock, flags);
200633b388fSRobert Foss 		return -EINVAL;
201633b388fSRobert Foss 	}
202633b388fSRobert Foss 	output->state = VFE_OUTPUT_IDLE;
203633b388fSRobert Foss 
204633b388fSRobert Foss 	output->buf[0] = vfe_buf_get_pending(output);
205633b388fSRobert Foss 	output->buf[1] = vfe_buf_get_pending(output);
206633b388fSRobert Foss 
207633b388fSRobert Foss 	if (!output->buf[0] && output->buf[1]) {
208633b388fSRobert Foss 		output->buf[0] = output->buf[1];
209633b388fSRobert Foss 		output->buf[1] = NULL;
210633b388fSRobert Foss 	}
211633b388fSRobert Foss 
212633b388fSRobert Foss 	if (output->buf[0])
213633b388fSRobert Foss 		output->state = VFE_OUTPUT_SINGLE;
214633b388fSRobert Foss 
215633b388fSRobert Foss 	if (output->buf[1])
216633b388fSRobert Foss 		output->state = VFE_OUTPUT_CONTINUOUS;
217633b388fSRobert Foss 
218633b388fSRobert Foss 	switch (output->state) {
219633b388fSRobert Foss 	case VFE_OUTPUT_SINGLE:
220633b388fSRobert Foss 		vfe_output_frame_drop(vfe, output, 1 << frame_skip);
221633b388fSRobert Foss 		break;
222633b388fSRobert Foss 	case VFE_OUTPUT_CONTINUOUS:
223633b388fSRobert Foss 		vfe_output_frame_drop(vfe, output, 3 << frame_skip);
224633b388fSRobert Foss 		break;
225633b388fSRobert Foss 	default:
226633b388fSRobert Foss 		vfe_output_frame_drop(vfe, output, 0);
227633b388fSRobert Foss 		break;
228633b388fSRobert Foss 	}
229633b388fSRobert Foss 
230633b388fSRobert Foss 	output->sequence = 0;
231633b388fSRobert Foss 	output->gen1.wait_sof = 0;
232633b388fSRobert Foss 	output->wait_reg_update = 0;
233633b388fSRobert Foss 	reinit_completion(&output->sof);
234633b388fSRobert Foss 	reinit_completion(&output->reg_update);
235633b388fSRobert Foss 
236633b388fSRobert Foss 	vfe_output_init_addrs(vfe, output, 0, line);
237633b388fSRobert Foss 
238633b388fSRobert Foss 	if (line->id != VFE_LINE_PIX) {
239633b388fSRobert Foss 		vfe->ops_gen1->set_cgc_override(vfe, output->wm_idx[0], 1);
240633b388fSRobert Foss 		vfe->ops_gen1->enable_irq_wm_line(vfe, output->wm_idx[0], line->id, 1);
241633b388fSRobert Foss 		vfe->ops_gen1->bus_connect_wm_to_rdi(vfe, output->wm_idx[0], line->id);
242633b388fSRobert Foss 		vfe->ops_gen1->wm_set_subsample(vfe, output->wm_idx[0]);
243633b388fSRobert Foss 		vfe->ops_gen1->set_rdi_cid(vfe, line->id, 0);
244633b388fSRobert Foss 		vfe->ops_gen1->wm_set_ub_cfg(vfe, output->wm_idx[0],
245633b388fSRobert Foss 					    (ub_size + 1) * output->wm_idx[0], ub_size);
246633b388fSRobert Foss 		vfe->ops_gen1->wm_frame_based(vfe, output->wm_idx[0], 1);
247633b388fSRobert Foss 		vfe->ops_gen1->wm_enable(vfe, output->wm_idx[0], 1);
248633b388fSRobert Foss 		vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[0]);
249633b388fSRobert Foss 	} else {
250633b388fSRobert Foss 		ub_size /= output->wm_num;
251633b388fSRobert Foss 		for (i = 0; i < output->wm_num; i++) {
252633b388fSRobert Foss 			vfe->ops_gen1->set_cgc_override(vfe, output->wm_idx[i], 1);
253633b388fSRobert Foss 			vfe->ops_gen1->wm_set_subsample(vfe, output->wm_idx[i]);
254633b388fSRobert Foss 			vfe->ops_gen1->wm_set_ub_cfg(vfe, output->wm_idx[i],
255633b388fSRobert Foss 						     (ub_size + 1) * output->wm_idx[i], ub_size);
256633b388fSRobert Foss 			vfe->ops_gen1->wm_line_based(vfe, output->wm_idx[i],
257633b388fSRobert Foss 						     &line->video_out.active_fmt.fmt.pix_mp, i, 1);
258633b388fSRobert Foss 			vfe->ops_gen1->wm_enable(vfe, output->wm_idx[i], 1);
259633b388fSRobert Foss 			vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[i]);
260633b388fSRobert Foss 		}
261633b388fSRobert Foss 		vfe->ops_gen1->enable_irq_pix_line(vfe, 0, line->id, 1);
262633b388fSRobert Foss 		vfe->ops_gen1->set_module_cfg(vfe, 1);
263633b388fSRobert Foss 		vfe->ops_gen1->set_camif_cfg(vfe, line);
264633b388fSRobert Foss 		vfe->ops_gen1->set_realign_cfg(vfe, line, 1);
265633b388fSRobert Foss 		vfe->ops_gen1->set_xbar_cfg(vfe, output, 1);
266633b388fSRobert Foss 		vfe->ops_gen1->set_demux_cfg(vfe, line);
267633b388fSRobert Foss 		vfe->ops_gen1->set_scale_cfg(vfe, line);
268633b388fSRobert Foss 		vfe->ops_gen1->set_crop_cfg(vfe, line);
269633b388fSRobert Foss 		vfe->ops_gen1->set_clamp_cfg(vfe);
270633b388fSRobert Foss 		vfe->ops_gen1->set_camif_cmd(vfe, 1);
271633b388fSRobert Foss 	}
272633b388fSRobert Foss 
273633b388fSRobert Foss 	ops->reg_update(vfe, line->id);
274633b388fSRobert Foss 
275633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
276633b388fSRobert Foss 
277633b388fSRobert Foss 	return 0;
278633b388fSRobert Foss }
279633b388fSRobert Foss 
vfe_get_output(struct vfe_line * line)280633b388fSRobert Foss static int vfe_get_output(struct vfe_line *line)
281633b388fSRobert Foss {
282633b388fSRobert Foss 	struct vfe_device *vfe = to_vfe(line);
283633b388fSRobert Foss 	struct vfe_output *output;
284633b388fSRobert Foss 	struct v4l2_format *f = &line->video_out.active_fmt;
285633b388fSRobert Foss 	unsigned long flags;
286633b388fSRobert Foss 	int i;
287633b388fSRobert Foss 	int wm_idx;
288633b388fSRobert Foss 
289633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
290633b388fSRobert Foss 
291633b388fSRobert Foss 	output = &line->output;
292*8ce158c1SMilen Mitkov 	if (output->state > VFE_OUTPUT_RESERVED) {
293633b388fSRobert Foss 		dev_err(vfe->camss->dev, "Output is running\n");
294633b388fSRobert Foss 		goto error;
295633b388fSRobert Foss 	}
296633b388fSRobert Foss 	output->state = VFE_OUTPUT_RESERVED;
297633b388fSRobert Foss 
298633b388fSRobert Foss 	output->gen1.active_buf = 0;
299633b388fSRobert Foss 
300633b388fSRobert Foss 	switch (f->fmt.pix_mp.pixelformat) {
301633b388fSRobert Foss 	case V4L2_PIX_FMT_NV12:
302633b388fSRobert Foss 	case V4L2_PIX_FMT_NV21:
303633b388fSRobert Foss 	case V4L2_PIX_FMT_NV16:
304633b388fSRobert Foss 	case V4L2_PIX_FMT_NV61:
305633b388fSRobert Foss 		output->wm_num = 2;
306633b388fSRobert Foss 		break;
307633b388fSRobert Foss 	default:
308633b388fSRobert Foss 		output->wm_num = 1;
309633b388fSRobert Foss 		break;
310633b388fSRobert Foss 	}
311633b388fSRobert Foss 
312633b388fSRobert Foss 	for (i = 0; i < output->wm_num; i++) {
313633b388fSRobert Foss 		wm_idx = vfe_reserve_wm(vfe, line->id);
314633b388fSRobert Foss 		if (wm_idx < 0) {
315633b388fSRobert Foss 			dev_err(vfe->camss->dev, "Can not reserve wm\n");
316633b388fSRobert Foss 			goto error_get_wm;
317633b388fSRobert Foss 		}
318633b388fSRobert Foss 		output->wm_idx[i] = wm_idx;
319633b388fSRobert Foss 	}
320633b388fSRobert Foss 
321633b388fSRobert Foss 	output->drop_update_idx = 0;
322633b388fSRobert Foss 
323633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
324633b388fSRobert Foss 
325633b388fSRobert Foss 	return 0;
326633b388fSRobert Foss 
327633b388fSRobert Foss error_get_wm:
328633b388fSRobert Foss 	for (i--; i >= 0; i--)
329633b388fSRobert Foss 		vfe_release_wm(vfe, output->wm_idx[i]);
330633b388fSRobert Foss 	output->state = VFE_OUTPUT_OFF;
331633b388fSRobert Foss error:
332633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
333633b388fSRobert Foss 
334633b388fSRobert Foss 	return -EINVAL;
335633b388fSRobert Foss }
336633b388fSRobert Foss 
vfe_gen1_enable(struct vfe_line * line)337633b388fSRobert Foss int vfe_gen1_enable(struct vfe_line *line)
338633b388fSRobert Foss {
339633b388fSRobert Foss 	struct vfe_device *vfe = to_vfe(line);
340633b388fSRobert Foss 	int ret;
341633b388fSRobert Foss 
342633b388fSRobert Foss 	mutex_lock(&vfe->stream_lock);
343633b388fSRobert Foss 
344633b388fSRobert Foss 	if (!vfe->stream_count) {
345633b388fSRobert Foss 		vfe->ops_gen1->enable_irq_common(vfe);
346633b388fSRobert Foss 		vfe->ops_gen1->bus_enable_wr_if(vfe, 1);
347633b388fSRobert Foss 		vfe->ops_gen1->set_qos(vfe);
348633b388fSRobert Foss 		vfe->ops_gen1->set_ds(vfe);
349633b388fSRobert Foss 	}
350633b388fSRobert Foss 
351633b388fSRobert Foss 	vfe->stream_count++;
352633b388fSRobert Foss 
353633b388fSRobert Foss 	mutex_unlock(&vfe->stream_lock);
354633b388fSRobert Foss 
355633b388fSRobert Foss 	ret = vfe_get_output(line);
356633b388fSRobert Foss 	if (ret < 0)
357633b388fSRobert Foss 		goto error_get_output;
358633b388fSRobert Foss 
359633b388fSRobert Foss 	ret = vfe_enable_output(line);
360633b388fSRobert Foss 	if (ret < 0)
361633b388fSRobert Foss 		goto error_enable_output;
362633b388fSRobert Foss 
363633b388fSRobert Foss 	vfe->was_streaming = 1;
364633b388fSRobert Foss 
365633b388fSRobert Foss 	return 0;
366633b388fSRobert Foss 
367633b388fSRobert Foss error_enable_output:
368633b388fSRobert Foss 	vfe_put_output(line);
369633b388fSRobert Foss 
370633b388fSRobert Foss error_get_output:
371633b388fSRobert Foss 	mutex_lock(&vfe->stream_lock);
372633b388fSRobert Foss 
373633b388fSRobert Foss 	if (vfe->stream_count == 1)
374633b388fSRobert Foss 		vfe->ops_gen1->bus_enable_wr_if(vfe, 0);
375633b388fSRobert Foss 
376633b388fSRobert Foss 	vfe->stream_count--;
377633b388fSRobert Foss 
378633b388fSRobert Foss 	mutex_unlock(&vfe->stream_lock);
379633b388fSRobert Foss 
380633b388fSRobert Foss 	return ret;
381633b388fSRobert Foss }
382633b388fSRobert Foss 
vfe_output_update_ping_addr(struct vfe_device * vfe,struct vfe_output * output,u8 sync,struct vfe_line * line)383633b388fSRobert Foss static void vfe_output_update_ping_addr(struct vfe_device *vfe,
384633b388fSRobert Foss 					struct vfe_output *output, u8 sync,
385633b388fSRobert Foss 					struct vfe_line *line)
386633b388fSRobert Foss {
387633b388fSRobert Foss 	u32 addr;
388633b388fSRobert Foss 	unsigned int i;
389633b388fSRobert Foss 
390633b388fSRobert Foss 	for (i = 0; i < output->wm_num; i++) {
391633b388fSRobert Foss 		if (output->buf[0])
392633b388fSRobert Foss 			addr = output->buf[0]->addr[i];
393633b388fSRobert Foss 		else
394633b388fSRobert Foss 			addr = 0;
395633b388fSRobert Foss 
396633b388fSRobert Foss 		vfe->ops_gen1->wm_set_ping_addr(vfe, output->wm_idx[i], addr);
397633b388fSRobert Foss 		if (sync)
398633b388fSRobert Foss 			vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[i]);
399633b388fSRobert Foss 	}
400633b388fSRobert Foss }
401633b388fSRobert Foss 
vfe_output_update_pong_addr(struct vfe_device * vfe,struct vfe_output * output,u8 sync,struct vfe_line * line)402633b388fSRobert Foss static void vfe_output_update_pong_addr(struct vfe_device *vfe,
403633b388fSRobert Foss 					struct vfe_output *output, u8 sync,
404633b388fSRobert Foss 					struct vfe_line *line)
405633b388fSRobert Foss {
406633b388fSRobert Foss 	u32 addr;
407633b388fSRobert Foss 	unsigned int i;
408633b388fSRobert Foss 
409633b388fSRobert Foss 	for (i = 0; i < output->wm_num; i++) {
410633b388fSRobert Foss 		if (output->buf[1])
411633b388fSRobert Foss 			addr = output->buf[1]->addr[i];
412633b388fSRobert Foss 		else
413633b388fSRobert Foss 			addr = 0;
414633b388fSRobert Foss 
415633b388fSRobert Foss 		vfe->ops_gen1->wm_set_pong_addr(vfe, output->wm_idx[i], addr);
416633b388fSRobert Foss 		if (sync)
417633b388fSRobert Foss 			vfe->ops_gen1->bus_reload_wm(vfe, output->wm_idx[i]);
418633b388fSRobert Foss 	}
419633b388fSRobert Foss }
420633b388fSRobert Foss 
vfe_buf_update_wm_on_next(struct vfe_device * vfe,struct vfe_output * output)421633b388fSRobert Foss static void vfe_buf_update_wm_on_next(struct vfe_device *vfe,
422633b388fSRobert Foss 				      struct vfe_output *output)
423633b388fSRobert Foss {
424633b388fSRobert Foss 	switch (output->state) {
425633b388fSRobert Foss 	case VFE_OUTPUT_CONTINUOUS:
426633b388fSRobert Foss 		vfe_output_frame_drop(vfe, output, 3);
427633b388fSRobert Foss 		break;
428633b388fSRobert Foss 	case VFE_OUTPUT_SINGLE:
429633b388fSRobert Foss 	default:
430633b388fSRobert Foss 		dev_err_ratelimited(vfe->camss->dev,
431633b388fSRobert Foss 				    "Next buf in wrong state! %d\n",
432633b388fSRobert Foss 				    output->state);
433633b388fSRobert Foss 		break;
434633b388fSRobert Foss 	}
435633b388fSRobert Foss }
436633b388fSRobert Foss 
vfe_buf_update_wm_on_last(struct vfe_device * vfe,struct vfe_output * output)437633b388fSRobert Foss static void vfe_buf_update_wm_on_last(struct vfe_device *vfe,
438633b388fSRobert Foss 				      struct vfe_output *output)
439633b388fSRobert Foss {
440633b388fSRobert Foss 	switch (output->state) {
441633b388fSRobert Foss 	case VFE_OUTPUT_CONTINUOUS:
442633b388fSRobert Foss 		output->state = VFE_OUTPUT_SINGLE;
443633b388fSRobert Foss 		vfe_output_frame_drop(vfe, output, 1);
444633b388fSRobert Foss 		break;
445633b388fSRobert Foss 	case VFE_OUTPUT_SINGLE:
446633b388fSRobert Foss 		output->state = VFE_OUTPUT_STOPPING;
447633b388fSRobert Foss 		vfe_output_frame_drop(vfe, output, 0);
448633b388fSRobert Foss 		break;
449633b388fSRobert Foss 	default:
450633b388fSRobert Foss 		dev_err_ratelimited(vfe->camss->dev,
451633b388fSRobert Foss 				    "Last buff in wrong state! %d\n",
452633b388fSRobert Foss 				    output->state);
453633b388fSRobert Foss 		break;
454633b388fSRobert Foss 	}
455633b388fSRobert Foss }
456633b388fSRobert Foss 
vfe_buf_update_wm_on_new(struct vfe_device * vfe,struct vfe_output * output,struct camss_buffer * new_buf,struct vfe_line * line)457633b388fSRobert Foss static void vfe_buf_update_wm_on_new(struct vfe_device *vfe,
458633b388fSRobert Foss 				     struct vfe_output *output,
459633b388fSRobert Foss 				     struct camss_buffer *new_buf,
460633b388fSRobert Foss 				     struct vfe_line *line)
461633b388fSRobert Foss {
462633b388fSRobert Foss 	int inactive_idx;
463633b388fSRobert Foss 
464633b388fSRobert Foss 	switch (output->state) {
465633b388fSRobert Foss 	case VFE_OUTPUT_SINGLE:
466633b388fSRobert Foss 		inactive_idx = !output->gen1.active_buf;
467633b388fSRobert Foss 
468633b388fSRobert Foss 		if (!output->buf[inactive_idx]) {
469633b388fSRobert Foss 			output->buf[inactive_idx] = new_buf;
470633b388fSRobert Foss 
471633b388fSRobert Foss 			if (inactive_idx)
472633b388fSRobert Foss 				vfe_output_update_pong_addr(vfe, output, 0, line);
473633b388fSRobert Foss 			else
474633b388fSRobert Foss 				vfe_output_update_ping_addr(vfe, output, 0, line);
475633b388fSRobert Foss 
476633b388fSRobert Foss 			vfe_output_frame_drop(vfe, output, 3);
477633b388fSRobert Foss 			output->state = VFE_OUTPUT_CONTINUOUS;
478633b388fSRobert Foss 		} else {
479633b388fSRobert Foss 			vfe_buf_add_pending(output, new_buf);
480633b388fSRobert Foss 			dev_err_ratelimited(vfe->camss->dev,
481633b388fSRobert Foss 					    "Inactive buffer is busy\n");
482633b388fSRobert Foss 		}
483633b388fSRobert Foss 		break;
484633b388fSRobert Foss 
485633b388fSRobert Foss 	case VFE_OUTPUT_IDLE:
486633b388fSRobert Foss 		if (!output->buf[0]) {
487633b388fSRobert Foss 			output->buf[0] = new_buf;
488633b388fSRobert Foss 
489633b388fSRobert Foss 			vfe_output_init_addrs(vfe, output, 1, line);
490633b388fSRobert Foss 			vfe_output_frame_drop(vfe, output, 1);
491633b388fSRobert Foss 
492633b388fSRobert Foss 			output->state = VFE_OUTPUT_SINGLE;
493633b388fSRobert Foss 		} else {
494633b388fSRobert Foss 			vfe_buf_add_pending(output, new_buf);
495633b388fSRobert Foss 			dev_err_ratelimited(vfe->camss->dev,
496633b388fSRobert Foss 					    "Output idle with buffer set!\n");
497633b388fSRobert Foss 		}
498633b388fSRobert Foss 		break;
499633b388fSRobert Foss 
500633b388fSRobert Foss 	case VFE_OUTPUT_CONTINUOUS:
501633b388fSRobert Foss 	default:
502633b388fSRobert Foss 		vfe_buf_add_pending(output, new_buf);
503633b388fSRobert Foss 		break;
504633b388fSRobert Foss 	}
505633b388fSRobert Foss }
506633b388fSRobert Foss 
507633b388fSRobert Foss /*
508633b388fSRobert Foss  * vfe_isr_halt_ack - Process halt ack
509633b388fSRobert Foss  * @vfe: VFE Device
510633b388fSRobert Foss  */
vfe_isr_halt_ack(struct vfe_device * vfe)511633b388fSRobert Foss static void vfe_isr_halt_ack(struct vfe_device *vfe)
512633b388fSRobert Foss {
513633b388fSRobert Foss 	complete(&vfe->halt_complete);
514633b388fSRobert Foss 	vfe->ops_gen1->halt_clear(vfe);
515633b388fSRobert Foss }
516633b388fSRobert Foss 
517633b388fSRobert Foss /*
518633b388fSRobert Foss  * vfe_isr_sof - Process start of frame interrupt
519633b388fSRobert Foss  * @vfe: VFE Device
520633b388fSRobert Foss  * @line_id: VFE line
521633b388fSRobert Foss  */
vfe_isr_sof(struct vfe_device * vfe,enum vfe_line_id line_id)522633b388fSRobert Foss static void vfe_isr_sof(struct vfe_device *vfe, enum vfe_line_id line_id)
523633b388fSRobert Foss {
524633b388fSRobert Foss 	struct vfe_output *output;
525633b388fSRobert Foss 	unsigned long flags;
526633b388fSRobert Foss 
527633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
528633b388fSRobert Foss 	output = &vfe->line[line_id].output;
529633b388fSRobert Foss 	if (output->gen1.wait_sof) {
530633b388fSRobert Foss 		output->gen1.wait_sof = 0;
531633b388fSRobert Foss 		complete(&output->sof);
532633b388fSRobert Foss 	}
533633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
534633b388fSRobert Foss }
535633b388fSRobert Foss 
536633b388fSRobert Foss /*
537633b388fSRobert Foss  * vfe_isr_reg_update - Process reg update interrupt
538633b388fSRobert Foss  * @vfe: VFE Device
539633b388fSRobert Foss  * @line_id: VFE line
540633b388fSRobert Foss  */
vfe_isr_reg_update(struct vfe_device * vfe,enum vfe_line_id line_id)541633b388fSRobert Foss static void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
542633b388fSRobert Foss {
543633b388fSRobert Foss 	struct vfe_output *output;
544633b388fSRobert Foss 	struct vfe_line *line = &vfe->line[line_id];
545633b388fSRobert Foss 	unsigned long flags;
546633b388fSRobert Foss 
547633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
548633b388fSRobert Foss 	vfe->ops->reg_update_clear(vfe, line_id);
549633b388fSRobert Foss 
550633b388fSRobert Foss 	output = &line->output;
551633b388fSRobert Foss 
552633b388fSRobert Foss 	if (output->wait_reg_update) {
553633b388fSRobert Foss 		output->wait_reg_update = 0;
554633b388fSRobert Foss 		complete(&output->reg_update);
555633b388fSRobert Foss 		spin_unlock_irqrestore(&vfe->output_lock, flags);
556633b388fSRobert Foss 		return;
557633b388fSRobert Foss 	}
558633b388fSRobert Foss 
559633b388fSRobert Foss 	if (output->state == VFE_OUTPUT_STOPPING) {
560633b388fSRobert Foss 		/* Release last buffer when hw is idle */
561633b388fSRobert Foss 		if (output->last_buffer) {
562633b388fSRobert Foss 			vb2_buffer_done(&output->last_buffer->vb.vb2_buf,
563633b388fSRobert Foss 					VB2_BUF_STATE_DONE);
564633b388fSRobert Foss 			output->last_buffer = NULL;
565633b388fSRobert Foss 		}
566633b388fSRobert Foss 		output->state = VFE_OUTPUT_IDLE;
567633b388fSRobert Foss 
568633b388fSRobert Foss 		/* Buffers received in stopping state are queued in */
569633b388fSRobert Foss 		/* dma pending queue, start next capture here */
570633b388fSRobert Foss 
571633b388fSRobert Foss 		output->buf[0] = vfe_buf_get_pending(output);
572633b388fSRobert Foss 		output->buf[1] = vfe_buf_get_pending(output);
573633b388fSRobert Foss 
574633b388fSRobert Foss 		if (!output->buf[0] && output->buf[1]) {
575633b388fSRobert Foss 			output->buf[0] = output->buf[1];
576633b388fSRobert Foss 			output->buf[1] = NULL;
577633b388fSRobert Foss 		}
578633b388fSRobert Foss 
579633b388fSRobert Foss 		if (output->buf[0])
580633b388fSRobert Foss 			output->state = VFE_OUTPUT_SINGLE;
581633b388fSRobert Foss 
582633b388fSRobert Foss 		if (output->buf[1])
583633b388fSRobert Foss 			output->state = VFE_OUTPUT_CONTINUOUS;
584633b388fSRobert Foss 
585633b388fSRobert Foss 		switch (output->state) {
586633b388fSRobert Foss 		case VFE_OUTPUT_SINGLE:
587633b388fSRobert Foss 			vfe_output_frame_drop(vfe, output, 2);
588633b388fSRobert Foss 			break;
589633b388fSRobert Foss 		case VFE_OUTPUT_CONTINUOUS:
590633b388fSRobert Foss 			vfe_output_frame_drop(vfe, output, 3);
591633b388fSRobert Foss 			break;
592633b388fSRobert Foss 		default:
593633b388fSRobert Foss 			vfe_output_frame_drop(vfe, output, 0);
594633b388fSRobert Foss 			break;
595633b388fSRobert Foss 		}
596633b388fSRobert Foss 
597633b388fSRobert Foss 		vfe_output_init_addrs(vfe, output, 1, &vfe->line[line_id]);
598633b388fSRobert Foss 	}
599633b388fSRobert Foss 
600633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
601633b388fSRobert Foss }
602633b388fSRobert Foss 
603633b388fSRobert Foss /*
604633b388fSRobert Foss  * vfe_isr_wm_done - Process write master done interrupt
605633b388fSRobert Foss  * @vfe: VFE Device
606633b388fSRobert Foss  * @wm: Write master id
607633b388fSRobert Foss  */
vfe_isr_wm_done(struct vfe_device * vfe,u8 wm)608633b388fSRobert Foss static void vfe_isr_wm_done(struct vfe_device *vfe, u8 wm)
609633b388fSRobert Foss {
610633b388fSRobert Foss 	struct camss_buffer *ready_buf;
611633b388fSRobert Foss 	struct vfe_output *output;
612633b388fSRobert Foss 	dma_addr_t *new_addr;
613633b388fSRobert Foss 	unsigned long flags;
614633b388fSRobert Foss 	u32 active_index;
615633b388fSRobert Foss 	u64 ts = ktime_get_ns();
616633b388fSRobert Foss 	unsigned int i;
617633b388fSRobert Foss 
618633b388fSRobert Foss 	active_index = vfe->ops_gen1->wm_get_ping_pong_status(vfe, wm);
619633b388fSRobert Foss 
620633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
621633b388fSRobert Foss 
622633b388fSRobert Foss 	if (vfe->wm_output_map[wm] == VFE_LINE_NONE) {
623633b388fSRobert Foss 		dev_err_ratelimited(vfe->camss->dev,
624633b388fSRobert Foss 				    "Received wm done for unmapped index\n");
625633b388fSRobert Foss 		goto out_unlock;
626633b388fSRobert Foss 	}
627633b388fSRobert Foss 	output = &vfe->line[vfe->wm_output_map[wm]].output;
628633b388fSRobert Foss 
629633b388fSRobert Foss 	if (output->gen1.active_buf == active_index && 0) {
630633b388fSRobert Foss 		dev_err_ratelimited(vfe->camss->dev,
631633b388fSRobert Foss 				    "Active buffer mismatch!\n");
632633b388fSRobert Foss 		goto out_unlock;
633633b388fSRobert Foss 	}
634633b388fSRobert Foss 	output->gen1.active_buf = active_index;
635633b388fSRobert Foss 
636633b388fSRobert Foss 	ready_buf = output->buf[!active_index];
637633b388fSRobert Foss 	if (!ready_buf) {
638633b388fSRobert Foss 		dev_err_ratelimited(vfe->camss->dev,
639633b388fSRobert Foss 				    "Missing ready buf %d %d!\n",
640633b388fSRobert Foss 				    !active_index, output->state);
641633b388fSRobert Foss 		goto out_unlock;
642633b388fSRobert Foss 	}
643633b388fSRobert Foss 
644633b388fSRobert Foss 	ready_buf->vb.vb2_buf.timestamp = ts;
645633b388fSRobert Foss 	ready_buf->vb.sequence = output->sequence++;
646633b388fSRobert Foss 
647633b388fSRobert Foss 	/* Get next buffer */
648633b388fSRobert Foss 	output->buf[!active_index] = vfe_buf_get_pending(output);
649633b388fSRobert Foss 	if (!output->buf[!active_index]) {
650633b388fSRobert Foss 		/* No next buffer - set same address */
651633b388fSRobert Foss 		new_addr = ready_buf->addr;
652633b388fSRobert Foss 		vfe_buf_update_wm_on_last(vfe, output);
653633b388fSRobert Foss 	} else {
654633b388fSRobert Foss 		new_addr = output->buf[!active_index]->addr;
655633b388fSRobert Foss 		vfe_buf_update_wm_on_next(vfe, output);
656633b388fSRobert Foss 	}
657633b388fSRobert Foss 
658633b388fSRobert Foss 	if (active_index)
659633b388fSRobert Foss 		for (i = 0; i < output->wm_num; i++)
660633b388fSRobert Foss 			vfe->ops_gen1->wm_set_ping_addr(vfe, output->wm_idx[i], new_addr[i]);
661633b388fSRobert Foss 	else
662633b388fSRobert Foss 		for (i = 0; i < output->wm_num; i++)
663633b388fSRobert Foss 			vfe->ops_gen1->wm_set_pong_addr(vfe, output->wm_idx[i], new_addr[i]);
664633b388fSRobert Foss 
665633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
666633b388fSRobert Foss 
667633b388fSRobert Foss 	if (output->state == VFE_OUTPUT_STOPPING)
668633b388fSRobert Foss 		output->last_buffer = ready_buf;
669633b388fSRobert Foss 	else
670633b388fSRobert Foss 		vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
671633b388fSRobert Foss 
672633b388fSRobert Foss 	return;
673633b388fSRobert Foss 
674633b388fSRobert Foss out_unlock:
675633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
676633b388fSRobert Foss }
677633b388fSRobert Foss 
678633b388fSRobert Foss /*
679633b388fSRobert Foss  * vfe_queue_buffer - Add empty buffer
680633b388fSRobert Foss  * @vid: Video device structure
681633b388fSRobert Foss  * @buf: Buffer to be enqueued
682633b388fSRobert Foss  *
683633b388fSRobert Foss  * Add an empty buffer - depending on the current number of buffers it will be
684633b388fSRobert Foss  * put in pending buffer queue or directly given to the hardware to be filled.
685633b388fSRobert Foss  *
686633b388fSRobert Foss  * Return 0 on success or a negative error code otherwise
687633b388fSRobert Foss  */
vfe_queue_buffer(struct camss_video * vid,struct camss_buffer * buf)688633b388fSRobert Foss static int vfe_queue_buffer(struct camss_video *vid, struct camss_buffer *buf)
689633b388fSRobert Foss {
690633b388fSRobert Foss 	struct vfe_line *line = container_of(vid, struct vfe_line, video_out);
691633b388fSRobert Foss 	struct vfe_device *vfe = to_vfe(line);
692633b388fSRobert Foss 	struct vfe_output *output;
693633b388fSRobert Foss 	unsigned long flags;
694633b388fSRobert Foss 
695633b388fSRobert Foss 	output = &line->output;
696633b388fSRobert Foss 
697633b388fSRobert Foss 	spin_lock_irqsave(&vfe->output_lock, flags);
698633b388fSRobert Foss 
699633b388fSRobert Foss 	vfe_buf_update_wm_on_new(vfe, output, buf, line);
700633b388fSRobert Foss 
701633b388fSRobert Foss 	spin_unlock_irqrestore(&vfe->output_lock, flags);
702633b388fSRobert Foss 
703633b388fSRobert Foss 	return 0;
704633b388fSRobert Foss }
705633b388fSRobert Foss 
706633b388fSRobert Foss #define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))
707633b388fSRobert Foss 
vfe_word_per_line(u32 format,u32 width)708633b388fSRobert Foss int vfe_word_per_line(u32 format, u32 width)
709633b388fSRobert Foss {
710633b388fSRobert Foss 	int val = 0;
711633b388fSRobert Foss 
712633b388fSRobert Foss 	switch (format) {
713633b388fSRobert Foss 	case V4L2_PIX_FMT_NV12:
714633b388fSRobert Foss 	case V4L2_PIX_FMT_NV21:
715633b388fSRobert Foss 	case V4L2_PIX_FMT_NV16:
716633b388fSRobert Foss 	case V4L2_PIX_FMT_NV61:
717633b388fSRobert Foss 		val = CALC_WORD(width, 1, 8);
718633b388fSRobert Foss 		break;
719633b388fSRobert Foss 	case V4L2_PIX_FMT_YUYV:
720633b388fSRobert Foss 	case V4L2_PIX_FMT_YVYU:
721633b388fSRobert Foss 	case V4L2_PIX_FMT_UYVY:
722633b388fSRobert Foss 	case V4L2_PIX_FMT_VYUY:
723633b388fSRobert Foss 		val = CALC_WORD(width, 2, 8);
724633b388fSRobert Foss 		break;
725633b388fSRobert Foss 	}
726633b388fSRobert Foss 
727633b388fSRobert Foss 	return val;
728633b388fSRobert Foss }
729633b388fSRobert Foss 
730633b388fSRobert Foss const struct vfe_isr_ops vfe_isr_ops_gen1 = {
731633b388fSRobert Foss 	.reset_ack = vfe_isr_reset_ack,
732633b388fSRobert Foss 	.halt_ack = vfe_isr_halt_ack,
733633b388fSRobert Foss 	.reg_update = vfe_isr_reg_update,
734633b388fSRobert Foss 	.sof = vfe_isr_sof,
735633b388fSRobert Foss 	.comp_done = vfe_isr_comp_done,
736633b388fSRobert Foss 	.wm_done = vfe_isr_wm_done,
737633b388fSRobert Foss };
738633b388fSRobert Foss 
739633b388fSRobert Foss const struct camss_video_ops vfe_video_ops_gen1 = {
740633b388fSRobert Foss 	.queue_buffer = vfe_queue_buffer,
741633b388fSRobert Foss 	.flush_buffers = vfe_flush_buffers,
742633b388fSRobert Foss };
743