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