xref: /OK3568_Linux_fs/kernel/drivers/media/test-drivers/vimc/vimc-common.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * vimc-common.c Virtual Media Controller Driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/init.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "vimc-common.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun  * NOTE: non-bayer formats need to come first (necessary for enum_mbus_code
15*4882a593Smuzhiyun  * in the scaler)
16*4882a593Smuzhiyun  */
17*4882a593Smuzhiyun static const struct vimc_pix_map vimc_pix_map_list[] = {
18*4882a593Smuzhiyun 	/* TODO: add all missing formats */
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 	/* RGB formats */
21*4882a593Smuzhiyun 	{
22*4882a593Smuzhiyun 		.code = {
23*4882a593Smuzhiyun 			MEDIA_BUS_FMT_BGR888_1X24,
24*4882a593Smuzhiyun 			MEDIA_BUS_FMT_BGR888_3X8
25*4882a593Smuzhiyun 		},
26*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_BGR24,
27*4882a593Smuzhiyun 		.bpp = 3,
28*4882a593Smuzhiyun 		.bayer = false,
29*4882a593Smuzhiyun 	},
30*4882a593Smuzhiyun 	{
31*4882a593Smuzhiyun 		.code = {
32*4882a593Smuzhiyun 			MEDIA_BUS_FMT_RGB888_1X24,
33*4882a593Smuzhiyun 			MEDIA_BUS_FMT_RGB888_2X12_BE,
34*4882a593Smuzhiyun 			MEDIA_BUS_FMT_RGB888_2X12_LE,
35*4882a593Smuzhiyun 			MEDIA_BUS_FMT_RGB888_3X8,
36*4882a593Smuzhiyun 			MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
37*4882a593Smuzhiyun 			MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
38*4882a593Smuzhiyun 			MEDIA_BUS_FMT_RGB888_1X32_PADHI,
39*4882a593Smuzhiyun 			MEDIA_BUS_FMT_GBR888_1X24
40*4882a593Smuzhiyun 		},
41*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_RGB24,
42*4882a593Smuzhiyun 		.bpp = 3,
43*4882a593Smuzhiyun 		.bayer = false,
44*4882a593Smuzhiyun 	},
45*4882a593Smuzhiyun 	{
46*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_ARGB8888_1X32 },
47*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_ARGB32,
48*4882a593Smuzhiyun 		.bpp = 4,
49*4882a593Smuzhiyun 		.bayer = false,
50*4882a593Smuzhiyun 	},
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	/* Bayer formats */
53*4882a593Smuzhiyun 	{
54*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SBGGR8_1X8 },
55*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SBGGR8,
56*4882a593Smuzhiyun 		.bpp = 1,
57*4882a593Smuzhiyun 		.bayer = true,
58*4882a593Smuzhiyun 	},
59*4882a593Smuzhiyun 	{
60*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGBRG8_1X8 },
61*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGBRG8,
62*4882a593Smuzhiyun 		.bpp = 1,
63*4882a593Smuzhiyun 		.bayer = true,
64*4882a593Smuzhiyun 	},
65*4882a593Smuzhiyun 	{
66*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGRBG8_1X8 },
67*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGRBG8,
68*4882a593Smuzhiyun 		.bpp = 1,
69*4882a593Smuzhiyun 		.bayer = true,
70*4882a593Smuzhiyun 	},
71*4882a593Smuzhiyun 	{
72*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SRGGB8_1X8 },
73*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SRGGB8,
74*4882a593Smuzhiyun 		.bpp = 1,
75*4882a593Smuzhiyun 		.bayer = true,
76*4882a593Smuzhiyun 	},
77*4882a593Smuzhiyun 	{
78*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SBGGR10_1X10 },
79*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SBGGR10,
80*4882a593Smuzhiyun 		.bpp = 2,
81*4882a593Smuzhiyun 		.bayer = true,
82*4882a593Smuzhiyun 	},
83*4882a593Smuzhiyun 	{
84*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGBRG10_1X10 },
85*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGBRG10,
86*4882a593Smuzhiyun 		.bpp = 2,
87*4882a593Smuzhiyun 		.bayer = true,
88*4882a593Smuzhiyun 	},
89*4882a593Smuzhiyun 	{
90*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGRBG10_1X10 },
91*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGRBG10,
92*4882a593Smuzhiyun 		.bpp = 2,
93*4882a593Smuzhiyun 		.bayer = true,
94*4882a593Smuzhiyun 	},
95*4882a593Smuzhiyun 	{
96*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SRGGB10_1X10 },
97*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SRGGB10,
98*4882a593Smuzhiyun 		.bpp = 2,
99*4882a593Smuzhiyun 		.bayer = true,
100*4882a593Smuzhiyun 	},
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	/* 10bit raw bayer a-law compressed to 8 bits */
103*4882a593Smuzhiyun 	{
104*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8 },
105*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SBGGR10ALAW8,
106*4882a593Smuzhiyun 		.bpp = 1,
107*4882a593Smuzhiyun 		.bayer = true,
108*4882a593Smuzhiyun 	},
109*4882a593Smuzhiyun 	{
110*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8 },
111*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGBRG10ALAW8,
112*4882a593Smuzhiyun 		.bpp = 1,
113*4882a593Smuzhiyun 		.bayer = true,
114*4882a593Smuzhiyun 	},
115*4882a593Smuzhiyun 	{
116*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8 },
117*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8,
118*4882a593Smuzhiyun 		.bpp = 1,
119*4882a593Smuzhiyun 		.bayer = true,
120*4882a593Smuzhiyun 	},
121*4882a593Smuzhiyun 	{
122*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8 },
123*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SRGGB10ALAW8,
124*4882a593Smuzhiyun 		.bpp = 1,
125*4882a593Smuzhiyun 		.bayer = true,
126*4882a593Smuzhiyun 	},
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	/* 10bit raw bayer DPCM compressed to 8 bits */
129*4882a593Smuzhiyun 	{
130*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 },
131*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SBGGR10DPCM8,
132*4882a593Smuzhiyun 		.bpp = 1,
133*4882a593Smuzhiyun 		.bayer = true,
134*4882a593Smuzhiyun 	},
135*4882a593Smuzhiyun 	{
136*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 },
137*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGBRG10DPCM8,
138*4882a593Smuzhiyun 		.bpp = 1,
139*4882a593Smuzhiyun 		.bayer = true,
140*4882a593Smuzhiyun 	},
141*4882a593Smuzhiyun 	{
142*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 },
143*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
144*4882a593Smuzhiyun 		.bpp = 1,
145*4882a593Smuzhiyun 		.bayer = true,
146*4882a593Smuzhiyun 	},
147*4882a593Smuzhiyun 	{
148*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 },
149*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SRGGB10DPCM8,
150*4882a593Smuzhiyun 		.bpp = 1,
151*4882a593Smuzhiyun 		.bayer = true,
152*4882a593Smuzhiyun 	},
153*4882a593Smuzhiyun 	{
154*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SBGGR12_1X12 },
155*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SBGGR12,
156*4882a593Smuzhiyun 		.bpp = 2,
157*4882a593Smuzhiyun 		.bayer = true,
158*4882a593Smuzhiyun 	},
159*4882a593Smuzhiyun 	{
160*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGBRG12_1X12 },
161*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGBRG12,
162*4882a593Smuzhiyun 		.bpp = 2,
163*4882a593Smuzhiyun 		.bayer = true,
164*4882a593Smuzhiyun 	},
165*4882a593Smuzhiyun 	{
166*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SGRBG12_1X12 },
167*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SGRBG12,
168*4882a593Smuzhiyun 		.bpp = 2,
169*4882a593Smuzhiyun 		.bayer = true,
170*4882a593Smuzhiyun 	},
171*4882a593Smuzhiyun 	{
172*4882a593Smuzhiyun 		.code = { MEDIA_BUS_FMT_SRGGB12_1X12 },
173*4882a593Smuzhiyun 		.pixelformat = V4L2_PIX_FMT_SRGGB12,
174*4882a593Smuzhiyun 		.bpp = 2,
175*4882a593Smuzhiyun 		.bayer = true,
176*4882a593Smuzhiyun 	},
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun 
vimc_is_source(struct media_entity * ent)179*4882a593Smuzhiyun bool vimc_is_source(struct media_entity *ent)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun 	unsigned int i;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	for (i = 0; i < ent->num_pads; i++)
184*4882a593Smuzhiyun 		if (ent->pads[i].flags & MEDIA_PAD_FL_SINK)
185*4882a593Smuzhiyun 			return false;
186*4882a593Smuzhiyun 	return true;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
vimc_pix_map_by_index(unsigned int i)189*4882a593Smuzhiyun const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	if (i >= ARRAY_SIZE(vimc_pix_map_list))
192*4882a593Smuzhiyun 		return NULL;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	return &vimc_pix_map_list[i];
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
vimc_mbus_code_by_index(unsigned int index)197*4882a593Smuzhiyun u32 vimc_mbus_code_by_index(unsigned int index)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	unsigned int i, j;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
202*4882a593Smuzhiyun 		for (j = 0; j < ARRAY_SIZE(vimc_pix_map_list[i].code); j++) {
203*4882a593Smuzhiyun 			if (!vimc_pix_map_list[i].code[j])
204*4882a593Smuzhiyun 				break;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 			if (!index)
207*4882a593Smuzhiyun 				return vimc_pix_map_list[i].code[j];
208*4882a593Smuzhiyun 			index--;
209*4882a593Smuzhiyun 		}
210*4882a593Smuzhiyun 	}
211*4882a593Smuzhiyun 	return 0;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun 
vimc_pix_map_by_code(u32 code)214*4882a593Smuzhiyun const struct vimc_pix_map *vimc_pix_map_by_code(u32 code)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	unsigned int i, j;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
219*4882a593Smuzhiyun 		for (j = 0; j < ARRAY_SIZE(vimc_pix_map_list[i].code); j++) {
220*4882a593Smuzhiyun 			if (vimc_pix_map_list[i].code[j] == code)
221*4882a593Smuzhiyun 				return &vimc_pix_map_list[i];
222*4882a593Smuzhiyun 		}
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 	return NULL;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
vimc_pix_map_by_pixelformat(u32 pixelformat)227*4882a593Smuzhiyun const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun 	unsigned int i;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
232*4882a593Smuzhiyun 		if (vimc_pix_map_list[i].pixelformat == pixelformat)
233*4882a593Smuzhiyun 			return &vimc_pix_map_list[i];
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 	return NULL;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
vimc_get_pix_format(struct media_pad * pad,struct v4l2_pix_format * fmt)238*4882a593Smuzhiyun static int vimc_get_pix_format(struct media_pad *pad,
239*4882a593Smuzhiyun 			       struct v4l2_pix_format *fmt)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	if (is_media_entity_v4l2_subdev(pad->entity)) {
242*4882a593Smuzhiyun 		struct v4l2_subdev *sd =
243*4882a593Smuzhiyun 			media_entity_to_v4l2_subdev(pad->entity);
244*4882a593Smuzhiyun 		struct v4l2_subdev_format sd_fmt;
245*4882a593Smuzhiyun 		const struct vimc_pix_map *pix_map;
246*4882a593Smuzhiyun 		int ret;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 		sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
249*4882a593Smuzhiyun 		sd_fmt.pad = pad->index;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 		ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt);
252*4882a593Smuzhiyun 		if (ret)
253*4882a593Smuzhiyun 			return ret;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 		v4l2_fill_pix_format(fmt, &sd_fmt.format);
256*4882a593Smuzhiyun 		pix_map = vimc_pix_map_by_code(sd_fmt.format.code);
257*4882a593Smuzhiyun 		fmt->pixelformat = pix_map->pixelformat;
258*4882a593Smuzhiyun 	} else if (is_media_entity_v4l2_video_device(pad->entity)) {
259*4882a593Smuzhiyun 		struct video_device *vdev = container_of(pad->entity,
260*4882a593Smuzhiyun 							 struct video_device,
261*4882a593Smuzhiyun 							 entity);
262*4882a593Smuzhiyun 		struct vimc_ent_device *ved = video_get_drvdata(vdev);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 		if (!ved->vdev_get_format)
265*4882a593Smuzhiyun 			return -ENOIOCTLCMD;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 		ved->vdev_get_format(ved, fmt);
268*4882a593Smuzhiyun 	} else {
269*4882a593Smuzhiyun 		return -EINVAL;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	return 0;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
vimc_vdev_link_validate(struct media_link * link)275*4882a593Smuzhiyun int vimc_vdev_link_validate(struct media_link *link)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun 	struct v4l2_pix_format source_fmt, sink_fmt;
278*4882a593Smuzhiyun 	int ret;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	ret = vimc_get_pix_format(link->source, &source_fmt);
281*4882a593Smuzhiyun 	if (ret)
282*4882a593Smuzhiyun 		return ret;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	ret = vimc_get_pix_format(link->sink, &sink_fmt);
285*4882a593Smuzhiyun 	if (ret)
286*4882a593Smuzhiyun 		return ret;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	pr_info("vimc link validate: "
289*4882a593Smuzhiyun 		"%s:src:%dx%d (0x%x, %d, %d, %d, %d) "
290*4882a593Smuzhiyun 		"%s:snk:%dx%d (0x%x, %d, %d, %d, %d)\n",
291*4882a593Smuzhiyun 		/* src */
292*4882a593Smuzhiyun 		link->source->entity->name,
293*4882a593Smuzhiyun 		source_fmt.width, source_fmt.height,
294*4882a593Smuzhiyun 		source_fmt.pixelformat, source_fmt.colorspace,
295*4882a593Smuzhiyun 		source_fmt.quantization, source_fmt.xfer_func,
296*4882a593Smuzhiyun 		source_fmt.ycbcr_enc,
297*4882a593Smuzhiyun 		/* sink */
298*4882a593Smuzhiyun 		link->sink->entity->name,
299*4882a593Smuzhiyun 		sink_fmt.width, sink_fmt.height,
300*4882a593Smuzhiyun 		sink_fmt.pixelformat, sink_fmt.colorspace,
301*4882a593Smuzhiyun 		sink_fmt.quantization, sink_fmt.xfer_func,
302*4882a593Smuzhiyun 		sink_fmt.ycbcr_enc);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	/* The width, height and pixelformat must match. */
305*4882a593Smuzhiyun 	if (source_fmt.width != sink_fmt.width ||
306*4882a593Smuzhiyun 	    source_fmt.height != sink_fmt.height ||
307*4882a593Smuzhiyun 	    source_fmt.pixelformat != sink_fmt.pixelformat)
308*4882a593Smuzhiyun 		return -EPIPE;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	/*
311*4882a593Smuzhiyun 	 * The field order must match, or the sink field order must be NONE
312*4882a593Smuzhiyun 	 * to support interlaced hardware connected to bridges that support
313*4882a593Smuzhiyun 	 * progressive formats only.
314*4882a593Smuzhiyun 	 */
315*4882a593Smuzhiyun 	if (source_fmt.field != sink_fmt.field &&
316*4882a593Smuzhiyun 	    sink_fmt.field != V4L2_FIELD_NONE)
317*4882a593Smuzhiyun 		return -EPIPE;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	/*
320*4882a593Smuzhiyun 	 * If colorspace is DEFAULT, then assume all the colorimetry is also
321*4882a593Smuzhiyun 	 * DEFAULT, return 0 to skip comparing the other colorimetry parameters
322*4882a593Smuzhiyun 	 */
323*4882a593Smuzhiyun 	if (source_fmt.colorspace == V4L2_COLORSPACE_DEFAULT ||
324*4882a593Smuzhiyun 	    sink_fmt.colorspace == V4L2_COLORSPACE_DEFAULT)
325*4882a593Smuzhiyun 		return 0;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	/* Colorspace must match. */
328*4882a593Smuzhiyun 	if (source_fmt.colorspace != sink_fmt.colorspace)
329*4882a593Smuzhiyun 		return -EPIPE;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	/* Colorimetry must match if they are not set to DEFAULT */
332*4882a593Smuzhiyun 	if (source_fmt.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT &&
333*4882a593Smuzhiyun 	    sink_fmt.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT &&
334*4882a593Smuzhiyun 	    source_fmt.ycbcr_enc != sink_fmt.ycbcr_enc)
335*4882a593Smuzhiyun 		return -EPIPE;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (source_fmt.quantization != V4L2_QUANTIZATION_DEFAULT &&
338*4882a593Smuzhiyun 	    sink_fmt.quantization != V4L2_QUANTIZATION_DEFAULT &&
339*4882a593Smuzhiyun 	    source_fmt.quantization != sink_fmt.quantization)
340*4882a593Smuzhiyun 		return -EPIPE;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	if (source_fmt.xfer_func != V4L2_XFER_FUNC_DEFAULT &&
343*4882a593Smuzhiyun 	    sink_fmt.xfer_func != V4L2_XFER_FUNC_DEFAULT &&
344*4882a593Smuzhiyun 	    source_fmt.xfer_func != sink_fmt.xfer_func)
345*4882a593Smuzhiyun 		return -EPIPE;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	return 0;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun static const struct media_entity_operations vimc_ent_sd_mops = {
351*4882a593Smuzhiyun 	.link_validate = v4l2_subdev_link_validate,
352*4882a593Smuzhiyun };
353*4882a593Smuzhiyun 
vimc_ent_sd_register(struct vimc_ent_device * ved,struct v4l2_subdev * sd,struct v4l2_device * v4l2_dev,const char * const name,u32 function,u16 num_pads,struct media_pad * pads,const struct v4l2_subdev_ops * sd_ops)354*4882a593Smuzhiyun int vimc_ent_sd_register(struct vimc_ent_device *ved,
355*4882a593Smuzhiyun 			 struct v4l2_subdev *sd,
356*4882a593Smuzhiyun 			 struct v4l2_device *v4l2_dev,
357*4882a593Smuzhiyun 			 const char *const name,
358*4882a593Smuzhiyun 			 u32 function,
359*4882a593Smuzhiyun 			 u16 num_pads,
360*4882a593Smuzhiyun 			 struct media_pad *pads,
361*4882a593Smuzhiyun 			 const struct v4l2_subdev_ops *sd_ops)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	int ret;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	/* Fill the vimc_ent_device struct */
366*4882a593Smuzhiyun 	ved->ent = &sd->entity;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	/* Initialize the subdev */
369*4882a593Smuzhiyun 	v4l2_subdev_init(sd, sd_ops);
370*4882a593Smuzhiyun 	sd->entity.function = function;
371*4882a593Smuzhiyun 	sd->entity.ops = &vimc_ent_sd_mops;
372*4882a593Smuzhiyun 	sd->owner = THIS_MODULE;
373*4882a593Smuzhiyun 	strscpy(sd->name, name, sizeof(sd->name));
374*4882a593Smuzhiyun 	v4l2_set_subdevdata(sd, ved);
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	/* Expose this subdev to user space */
377*4882a593Smuzhiyun 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
378*4882a593Smuzhiyun 	if (sd->ctrl_handler)
379*4882a593Smuzhiyun 		sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	/* Initialize the media entity */
382*4882a593Smuzhiyun 	ret = media_entity_pads_init(&sd->entity, num_pads, pads);
383*4882a593Smuzhiyun 	if (ret)
384*4882a593Smuzhiyun 		return ret;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	/* Register the subdev with the v4l2 and the media framework */
387*4882a593Smuzhiyun 	ret = v4l2_device_register_subdev(v4l2_dev, sd);
388*4882a593Smuzhiyun 	if (ret) {
389*4882a593Smuzhiyun 		dev_err(v4l2_dev->dev,
390*4882a593Smuzhiyun 			"%s: subdev register failed (err=%d)\n",
391*4882a593Smuzhiyun 			name, ret);
392*4882a593Smuzhiyun 		goto err_clean_m_ent;
393*4882a593Smuzhiyun 	}
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	return 0;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun err_clean_m_ent:
398*4882a593Smuzhiyun 	media_entity_cleanup(&sd->entity);
399*4882a593Smuzhiyun 	return ret;
400*4882a593Smuzhiyun }
401