1ee4a77a3SMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0+
2ee4a77a3SMauro Carvalho Chehab /*
3ee4a77a3SMauro Carvalho Chehab  * vsp1_rwpf.c  --  R-Car VSP1 Read and Write Pixel Formatters
4ee4a77a3SMauro Carvalho Chehab  *
5ee4a77a3SMauro Carvalho Chehab  * Copyright (C) 2013-2014 Renesas Electronics Corporation
6ee4a77a3SMauro Carvalho Chehab  *
7ee4a77a3SMauro Carvalho Chehab  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8ee4a77a3SMauro Carvalho Chehab  */
9ee4a77a3SMauro Carvalho Chehab 
10ee4a77a3SMauro Carvalho Chehab #include <media/v4l2-subdev.h>
11ee4a77a3SMauro Carvalho Chehab 
12ee4a77a3SMauro Carvalho Chehab #include "vsp1.h"
13ee4a77a3SMauro Carvalho Chehab #include "vsp1_rwpf.h"
14ee4a77a3SMauro Carvalho Chehab #include "vsp1_video.h"
15ee4a77a3SMauro Carvalho Chehab 
16ee4a77a3SMauro Carvalho Chehab #define RWPF_MIN_WIDTH				1
17ee4a77a3SMauro Carvalho Chehab #define RWPF_MIN_HEIGHT				1
18ee4a77a3SMauro Carvalho Chehab 
vsp1_rwpf_get_crop(struct vsp1_rwpf * rwpf,struct v4l2_subdev_state * sd_state)19ee4a77a3SMauro Carvalho Chehab struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf,
20ee4a77a3SMauro Carvalho Chehab 				     struct v4l2_subdev_state *sd_state)
21ee4a77a3SMauro Carvalho Chehab {
22ee4a77a3SMauro Carvalho Chehab 	return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, sd_state,
23ee4a77a3SMauro Carvalho Chehab 					RWPF_PAD_SINK);
24ee4a77a3SMauro Carvalho Chehab }
25ee4a77a3SMauro Carvalho Chehab 
26ee4a77a3SMauro Carvalho Chehab /* -----------------------------------------------------------------------------
272948c1e5SLaurent Pinchart  * V4L2 Subdevice Operations
28ee4a77a3SMauro Carvalho Chehab  */
29ee4a77a3SMauro Carvalho Chehab 
vsp1_rwpf_enum_mbus_code(struct v4l2_subdev * subdev,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)30ee4a77a3SMauro Carvalho Chehab static int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev,
31ee4a77a3SMauro Carvalho Chehab 				    struct v4l2_subdev_state *sd_state,
32ee4a77a3SMauro Carvalho Chehab 				    struct v4l2_subdev_mbus_code_enum *code)
33ee4a77a3SMauro Carvalho Chehab {
34ee4a77a3SMauro Carvalho Chehab 	static const unsigned int codes[] = {
35ee4a77a3SMauro Carvalho Chehab 		MEDIA_BUS_FMT_ARGB8888_1X32,
36ee4a77a3SMauro Carvalho Chehab 		MEDIA_BUS_FMT_AHSV8888_1X32,
37ee4a77a3SMauro Carvalho Chehab 		MEDIA_BUS_FMT_AYUV8_1X32,
38ee4a77a3SMauro Carvalho Chehab 	};
39ee4a77a3SMauro Carvalho Chehab 
40ee4a77a3SMauro Carvalho Chehab 	if (code->index >= ARRAY_SIZE(codes))
41ee4a77a3SMauro Carvalho Chehab 		return -EINVAL;
42ee4a77a3SMauro Carvalho Chehab 
43ee4a77a3SMauro Carvalho Chehab 	code->code = codes[code->index];
44ee4a77a3SMauro Carvalho Chehab 
45ee4a77a3SMauro Carvalho Chehab 	return 0;
46ee4a77a3SMauro Carvalho Chehab }
47ee4a77a3SMauro Carvalho Chehab 
vsp1_rwpf_enum_frame_size(struct v4l2_subdev * subdev,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)48ee4a77a3SMauro Carvalho Chehab static int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev,
49ee4a77a3SMauro Carvalho Chehab 				     struct v4l2_subdev_state *sd_state,
50ee4a77a3SMauro Carvalho Chehab 				     struct v4l2_subdev_frame_size_enum *fse)
51ee4a77a3SMauro Carvalho Chehab {
52ee4a77a3SMauro Carvalho Chehab 	struct vsp1_rwpf *rwpf = to_rwpf(subdev);
53ee4a77a3SMauro Carvalho Chehab 
54ee4a77a3SMauro Carvalho Chehab 	return vsp1_subdev_enum_frame_size(subdev, sd_state, fse,
55ee4a77a3SMauro Carvalho Chehab 					   RWPF_MIN_WIDTH,
56ee4a77a3SMauro Carvalho Chehab 					   RWPF_MIN_HEIGHT, rwpf->max_width,
57ee4a77a3SMauro Carvalho Chehab 					   rwpf->max_height);
58ee4a77a3SMauro Carvalho Chehab }
59ee4a77a3SMauro Carvalho Chehab 
vsp1_rwpf_set_format(struct v4l2_subdev * subdev,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)60ee4a77a3SMauro Carvalho Chehab static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
61ee4a77a3SMauro Carvalho Chehab 				struct v4l2_subdev_state *sd_state,
62ee4a77a3SMauro Carvalho Chehab 				struct v4l2_subdev_format *fmt)
63ee4a77a3SMauro Carvalho Chehab {
64ee4a77a3SMauro Carvalho Chehab 	struct vsp1_rwpf *rwpf = to_rwpf(subdev);
65ee4a77a3SMauro Carvalho Chehab 	struct v4l2_subdev_state *config;
66ee4a77a3SMauro Carvalho Chehab 	struct v4l2_mbus_framefmt *format;
67ee4a77a3SMauro Carvalho Chehab 	int ret = 0;
68ee4a77a3SMauro Carvalho Chehab 
69ee4a77a3SMauro Carvalho Chehab 	mutex_lock(&rwpf->entity.lock);
70ee4a77a3SMauro Carvalho Chehab 
71ee4a77a3SMauro Carvalho Chehab 	config = vsp1_entity_get_pad_config(&rwpf->entity, sd_state,
72ee4a77a3SMauro Carvalho Chehab 					    fmt->which);
73ee4a77a3SMauro Carvalho Chehab 	if (!config) {
74ee4a77a3SMauro Carvalho Chehab 		ret = -EINVAL;
75ee4a77a3SMauro Carvalho Chehab 		goto done;
76ee4a77a3SMauro Carvalho Chehab 	}
77ee4a77a3SMauro Carvalho Chehab 
78ee4a77a3SMauro Carvalho Chehab 	/* Default to YUV if the requested format is not supported. */
79ee4a77a3SMauro Carvalho Chehab 	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
80ee4a77a3SMauro Carvalho Chehab 	    fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
81ee4a77a3SMauro Carvalho Chehab 	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
82ee4a77a3SMauro Carvalho Chehab 		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
83ee4a77a3SMauro Carvalho Chehab 
84ee4a77a3SMauro Carvalho Chehab 	format = vsp1_entity_get_pad_format(&rwpf->entity, config, fmt->pad);
85ee4a77a3SMauro Carvalho Chehab 
86ee4a77a3SMauro Carvalho Chehab 	if (fmt->pad == RWPF_PAD_SOURCE) {
87ee4a77a3SMauro Carvalho Chehab 		/*
88ee4a77a3SMauro Carvalho Chehab 		 * The RWPF performs format conversion but can't scale, only the
89ee4a77a3SMauro Carvalho Chehab 		 * format code can be changed on the source pad.
90ee4a77a3SMauro Carvalho Chehab 		 */
91ee4a77a3SMauro Carvalho Chehab 		format->code = fmt->format.code;
92ee4a77a3SMauro Carvalho Chehab 		fmt->format = *format;
93ee4a77a3SMauro Carvalho Chehab 		goto done;
94ee4a77a3SMauro Carvalho Chehab 	}
95ee4a77a3SMauro Carvalho Chehab 
96ee4a77a3SMauro Carvalho Chehab 	format->code = fmt->format.code;
97ee4a77a3SMauro Carvalho Chehab 	format->width = clamp_t(unsigned int, fmt->format.width,
98ee4a77a3SMauro Carvalho Chehab 				RWPF_MIN_WIDTH, rwpf->max_width);
99ee4a77a3SMauro Carvalho Chehab 	format->height = clamp_t(unsigned int, fmt->format.height,
100ee4a77a3SMauro Carvalho Chehab 				 RWPF_MIN_HEIGHT, rwpf->max_height);
101ee4a77a3SMauro Carvalho Chehab 	format->field = V4L2_FIELD_NONE;
102ee4a77a3SMauro Carvalho Chehab 	format->colorspace = V4L2_COLORSPACE_SRGB;
103ee4a77a3SMauro Carvalho Chehab 
104ee4a77a3SMauro Carvalho Chehab 	fmt->format = *format;
105ee4a77a3SMauro Carvalho Chehab 
106ee4a77a3SMauro Carvalho Chehab 	if (rwpf->entity.type == VSP1_ENTITY_RPF) {
107ee4a77a3SMauro Carvalho Chehab 		struct v4l2_rect *crop;
108ee4a77a3SMauro Carvalho Chehab 
109ee4a77a3SMauro Carvalho Chehab 		/* Update the sink crop rectangle. */
110ee4a77a3SMauro Carvalho Chehab 		crop = vsp1_rwpf_get_crop(rwpf, config);
111ee4a77a3SMauro Carvalho Chehab 		crop->left = 0;
112ee4a77a3SMauro Carvalho Chehab 		crop->top = 0;
113ee4a77a3SMauro Carvalho Chehab 		crop->width = fmt->format.width;
114ee4a77a3SMauro Carvalho Chehab 		crop->height = fmt->format.height;
115ee4a77a3SMauro Carvalho Chehab 	}
116ee4a77a3SMauro Carvalho Chehab 
117ee4a77a3SMauro Carvalho Chehab 	/* Propagate the format to the source pad. */
118ee4a77a3SMauro Carvalho Chehab 	format = vsp1_entity_get_pad_format(&rwpf->entity, config,
119ee4a77a3SMauro Carvalho Chehab 					    RWPF_PAD_SOURCE);
120ee4a77a3SMauro Carvalho Chehab 	*format = fmt->format;
121ee4a77a3SMauro Carvalho Chehab 
122ee4a77a3SMauro Carvalho Chehab 	if (rwpf->flip.rotate) {
123ee4a77a3SMauro Carvalho Chehab 		format->width = fmt->format.height;
124ee4a77a3SMauro Carvalho Chehab 		format->height = fmt->format.width;
125ee4a77a3SMauro Carvalho Chehab 	}
126ee4a77a3SMauro Carvalho Chehab 
127ee4a77a3SMauro Carvalho Chehab done:
128ee4a77a3SMauro Carvalho Chehab 	mutex_unlock(&rwpf->entity.lock);
129ee4a77a3SMauro Carvalho Chehab 	return ret;
130ee4a77a3SMauro Carvalho Chehab }
131ee4a77a3SMauro Carvalho Chehab 
vsp1_rwpf_get_selection(struct v4l2_subdev * subdev,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_selection * sel)132ee4a77a3SMauro Carvalho Chehab static int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev,
133ee4a77a3SMauro Carvalho Chehab 				   struct v4l2_subdev_state *sd_state,
134ee4a77a3SMauro Carvalho Chehab 				   struct v4l2_subdev_selection *sel)
135ee4a77a3SMauro Carvalho Chehab {
136ee4a77a3SMauro Carvalho Chehab 	struct vsp1_rwpf *rwpf = to_rwpf(subdev);
137ee4a77a3SMauro Carvalho Chehab 	struct v4l2_subdev_state *config;
138ee4a77a3SMauro Carvalho Chehab 	struct v4l2_mbus_framefmt *format;
139ee4a77a3SMauro Carvalho Chehab 	int ret = 0;
140ee4a77a3SMauro Carvalho Chehab 
141ee4a77a3SMauro Carvalho Chehab 	/*
142ee4a77a3SMauro Carvalho Chehab 	 * Cropping is only supported on the RPF and is implemented on the sink
143ee4a77a3SMauro Carvalho Chehab 	 * pad.
144ee4a77a3SMauro Carvalho Chehab 	 */
145ee4a77a3SMauro Carvalho Chehab 	if (rwpf->entity.type == VSP1_ENTITY_WPF || sel->pad != RWPF_PAD_SINK)
146ee4a77a3SMauro Carvalho Chehab 		return -EINVAL;
147ee4a77a3SMauro Carvalho Chehab 
148ee4a77a3SMauro Carvalho Chehab 	mutex_lock(&rwpf->entity.lock);
149ee4a77a3SMauro Carvalho Chehab 
150ee4a77a3SMauro Carvalho Chehab 	config = vsp1_entity_get_pad_config(&rwpf->entity, sd_state,
151ee4a77a3SMauro Carvalho Chehab 					    sel->which);
152ee4a77a3SMauro Carvalho Chehab 	if (!config) {
153ee4a77a3SMauro Carvalho Chehab 		ret = -EINVAL;
154ee4a77a3SMauro Carvalho Chehab 		goto done;
155ee4a77a3SMauro Carvalho Chehab 	}
156ee4a77a3SMauro Carvalho Chehab 
157ee4a77a3SMauro Carvalho Chehab 	switch (sel->target) {
158ee4a77a3SMauro Carvalho Chehab 	case V4L2_SEL_TGT_CROP:
159ee4a77a3SMauro Carvalho Chehab 		sel->r = *vsp1_rwpf_get_crop(rwpf, config);
160ee4a77a3SMauro Carvalho Chehab 		break;
161ee4a77a3SMauro Carvalho Chehab 
162ee4a77a3SMauro Carvalho Chehab 	case V4L2_SEL_TGT_CROP_BOUNDS:
163ee4a77a3SMauro Carvalho Chehab 		format = vsp1_entity_get_pad_format(&rwpf->entity, config,
164ee4a77a3SMauro Carvalho Chehab 						    RWPF_PAD_SINK);
165ee4a77a3SMauro Carvalho Chehab 		sel->r.left = 0;
166ee4a77a3SMauro Carvalho Chehab 		sel->r.top = 0;
167ee4a77a3SMauro Carvalho Chehab 		sel->r.width = format->width;
168ee4a77a3SMauro Carvalho Chehab 		sel->r.height = format->height;
169ee4a77a3SMauro Carvalho Chehab 		break;
170ee4a77a3SMauro Carvalho Chehab 
171ee4a77a3SMauro Carvalho Chehab 	default:
172ee4a77a3SMauro Carvalho Chehab 		ret = -EINVAL;
173ee4a77a3SMauro Carvalho Chehab 		break;
174ee4a77a3SMauro Carvalho Chehab 	}
175ee4a77a3SMauro Carvalho Chehab 
176ee4a77a3SMauro Carvalho Chehab done:
177ee4a77a3SMauro Carvalho Chehab 	mutex_unlock(&rwpf->entity.lock);
178ee4a77a3SMauro Carvalho Chehab 	return ret;
179ee4a77a3SMauro Carvalho Chehab }
180ee4a77a3SMauro Carvalho Chehab 
vsp1_rwpf_set_selection(struct v4l2_subdev * subdev,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_selection * sel)181ee4a77a3SMauro Carvalho Chehab static int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
182ee4a77a3SMauro Carvalho Chehab 				   struct v4l2_subdev_state *sd_state,
183ee4a77a3SMauro Carvalho Chehab 				   struct v4l2_subdev_selection *sel)
184ee4a77a3SMauro Carvalho Chehab {
185ee4a77a3SMauro Carvalho Chehab 	struct vsp1_rwpf *rwpf = to_rwpf(subdev);
186ee4a77a3SMauro Carvalho Chehab 	struct v4l2_subdev_state *config;
187ee4a77a3SMauro Carvalho Chehab 	struct v4l2_mbus_framefmt *format;
188ee4a77a3SMauro Carvalho Chehab 	struct v4l2_rect *crop;
189ee4a77a3SMauro Carvalho Chehab 	int ret = 0;
190ee4a77a3SMauro Carvalho Chehab 
191ee4a77a3SMauro Carvalho Chehab 	/*
192ee4a77a3SMauro Carvalho Chehab 	 * Cropping is only supported on the RPF and is implemented on the sink
193ee4a77a3SMauro Carvalho Chehab 	 * pad.
194ee4a77a3SMauro Carvalho Chehab 	 */
195ee4a77a3SMauro Carvalho Chehab 	if (rwpf->entity.type == VSP1_ENTITY_WPF || sel->pad != RWPF_PAD_SINK)
196ee4a77a3SMauro Carvalho Chehab 		return -EINVAL;
197ee4a77a3SMauro Carvalho Chehab 
198ee4a77a3SMauro Carvalho Chehab 	if (sel->target != V4L2_SEL_TGT_CROP)
199ee4a77a3SMauro Carvalho Chehab 		return -EINVAL;
200ee4a77a3SMauro Carvalho Chehab 
201ee4a77a3SMauro Carvalho Chehab 	mutex_lock(&rwpf->entity.lock);
202ee4a77a3SMauro Carvalho Chehab 
203ee4a77a3SMauro Carvalho Chehab 	config = vsp1_entity_get_pad_config(&rwpf->entity, sd_state,
204ee4a77a3SMauro Carvalho Chehab 					    sel->which);
205ee4a77a3SMauro Carvalho Chehab 	if (!config) {
206ee4a77a3SMauro Carvalho Chehab 		ret = -EINVAL;
207ee4a77a3SMauro Carvalho Chehab 		goto done;
208ee4a77a3SMauro Carvalho Chehab 	}
209ee4a77a3SMauro Carvalho Chehab 
210ee4a77a3SMauro Carvalho Chehab 	/* Make sure the crop rectangle is entirely contained in the image. */
211ee4a77a3SMauro Carvalho Chehab 	format = vsp1_entity_get_pad_format(&rwpf->entity, config,
212ee4a77a3SMauro Carvalho Chehab 					    RWPF_PAD_SINK);
213ee4a77a3SMauro Carvalho Chehab 
214ee4a77a3SMauro Carvalho Chehab 	/*
215ee4a77a3SMauro Carvalho Chehab 	 * Restrict the crop rectangle coordinates to multiples of 2 to avoid
216ee4a77a3SMauro Carvalho Chehab 	 * shifting the color plane.
217ee4a77a3SMauro Carvalho Chehab 	 */
218ee4a77a3SMauro Carvalho Chehab 	if (format->code == MEDIA_BUS_FMT_AYUV8_1X32) {
219ee4a77a3SMauro Carvalho Chehab 		sel->r.left = ALIGN(sel->r.left, 2);
220ee4a77a3SMauro Carvalho Chehab 		sel->r.top = ALIGN(sel->r.top, 2);
221ee4a77a3SMauro Carvalho Chehab 		sel->r.width = round_down(sel->r.width, 2);
222ee4a77a3SMauro Carvalho Chehab 		sel->r.height = round_down(sel->r.height, 2);
223ee4a77a3SMauro Carvalho Chehab 	}
224ee4a77a3SMauro Carvalho Chehab 
225ee4a77a3SMauro Carvalho Chehab 	sel->r.left = min_t(unsigned int, sel->r.left, format->width - 2);
226ee4a77a3SMauro Carvalho Chehab 	sel->r.top = min_t(unsigned int, sel->r.top, format->height - 2);
227ee4a77a3SMauro Carvalho Chehab 	sel->r.width = min_t(unsigned int, sel->r.width,
228ee4a77a3SMauro Carvalho Chehab 			     format->width - sel->r.left);
229ee4a77a3SMauro Carvalho Chehab 	sel->r.height = min_t(unsigned int, sel->r.height,
230ee4a77a3SMauro Carvalho Chehab 			      format->height - sel->r.top);
231ee4a77a3SMauro Carvalho Chehab 
232ee4a77a3SMauro Carvalho Chehab 	crop = vsp1_rwpf_get_crop(rwpf, config);
233ee4a77a3SMauro Carvalho Chehab 	*crop = sel->r;
234ee4a77a3SMauro Carvalho Chehab 
235ee4a77a3SMauro Carvalho Chehab 	/* Propagate the format to the source pad. */
236ee4a77a3SMauro Carvalho Chehab 	format = vsp1_entity_get_pad_format(&rwpf->entity, config,
237ee4a77a3SMauro Carvalho Chehab 					    RWPF_PAD_SOURCE);
238ee4a77a3SMauro Carvalho Chehab 	format->width = crop->width;
239ee4a77a3SMauro Carvalho Chehab 	format->height = crop->height;
240ee4a77a3SMauro Carvalho Chehab 
241ee4a77a3SMauro Carvalho Chehab done:
242ee4a77a3SMauro Carvalho Chehab 	mutex_unlock(&rwpf->entity.lock);
243ee4a77a3SMauro Carvalho Chehab 	return ret;
244ee4a77a3SMauro Carvalho Chehab }
245ee4a77a3SMauro Carvalho Chehab 
2462948c1e5SLaurent Pinchart static const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops = {
247ee4a77a3SMauro Carvalho Chehab 	.init_cfg = vsp1_entity_init_cfg,
248ee4a77a3SMauro Carvalho Chehab 	.enum_mbus_code = vsp1_rwpf_enum_mbus_code,
249ee4a77a3SMauro Carvalho Chehab 	.enum_frame_size = vsp1_rwpf_enum_frame_size,
250ee4a77a3SMauro Carvalho Chehab 	.get_fmt = vsp1_subdev_get_pad_format,
251ee4a77a3SMauro Carvalho Chehab 	.set_fmt = vsp1_rwpf_set_format,
252ee4a77a3SMauro Carvalho Chehab 	.get_selection = vsp1_rwpf_get_selection,
253ee4a77a3SMauro Carvalho Chehab 	.set_selection = vsp1_rwpf_set_selection,
254ee4a77a3SMauro Carvalho Chehab };
255ee4a77a3SMauro Carvalho Chehab 
2562948c1e5SLaurent Pinchart const struct v4l2_subdev_ops vsp1_rwpf_subdev_ops = {
2572948c1e5SLaurent Pinchart 	.pad    = &vsp1_rwpf_pad_ops,
2582948c1e5SLaurent Pinchart };
2592948c1e5SLaurent Pinchart 
260ee4a77a3SMauro Carvalho Chehab /* -----------------------------------------------------------------------------
261ee4a77a3SMauro Carvalho Chehab  * Controls
262ee4a77a3SMauro Carvalho Chehab  */
263ee4a77a3SMauro Carvalho Chehab 
vsp1_rwpf_s_ctrl(struct v4l2_ctrl * ctrl)264ee4a77a3SMauro Carvalho Chehab static int vsp1_rwpf_s_ctrl(struct v4l2_ctrl *ctrl)
265ee4a77a3SMauro Carvalho Chehab {
266ee4a77a3SMauro Carvalho Chehab 	struct vsp1_rwpf *rwpf =
267ee4a77a3SMauro Carvalho Chehab 		container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
268ee4a77a3SMauro Carvalho Chehab 
269ee4a77a3SMauro Carvalho Chehab 	switch (ctrl->id) {
270ee4a77a3SMauro Carvalho Chehab 	case V4L2_CID_ALPHA_COMPONENT:
271ee4a77a3SMauro Carvalho Chehab 		rwpf->alpha = ctrl->val;
272ee4a77a3SMauro Carvalho Chehab 		break;
273ee4a77a3SMauro Carvalho Chehab 	}
274ee4a77a3SMauro Carvalho Chehab 
275ee4a77a3SMauro Carvalho Chehab 	return 0;
276ee4a77a3SMauro Carvalho Chehab }
277ee4a77a3SMauro Carvalho Chehab 
278ee4a77a3SMauro Carvalho Chehab static const struct v4l2_ctrl_ops vsp1_rwpf_ctrl_ops = {
279ee4a77a3SMauro Carvalho Chehab 	.s_ctrl = vsp1_rwpf_s_ctrl,
280ee4a77a3SMauro Carvalho Chehab };
281ee4a77a3SMauro Carvalho Chehab 
vsp1_rwpf_init_ctrls(struct vsp1_rwpf * rwpf,unsigned int ncontrols)282ee4a77a3SMauro Carvalho Chehab int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf, unsigned int ncontrols)
283ee4a77a3SMauro Carvalho Chehab {
284ee4a77a3SMauro Carvalho Chehab 	v4l2_ctrl_handler_init(&rwpf->ctrls, ncontrols + 1);
285ee4a77a3SMauro Carvalho Chehab 	v4l2_ctrl_new_std(&rwpf->ctrls, &vsp1_rwpf_ctrl_ops,
286ee4a77a3SMauro Carvalho Chehab 			  V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
287ee4a77a3SMauro Carvalho Chehab 
288ee4a77a3SMauro Carvalho Chehab 	rwpf->entity.subdev.ctrl_handler = &rwpf->ctrls;
289ee4a77a3SMauro Carvalho Chehab 
290ee4a77a3SMauro Carvalho Chehab 	return rwpf->ctrls.error;
291ee4a77a3SMauro Carvalho Chehab }
292