]> rtime.felk.cvut.cz Git - zynq/linux.git/blob - drivers/media/platform/xilinx/xilinx-vip.c
v4l: xilinx: vip: Fix stride calculation
[zynq/linux.git] / drivers / media / platform / xilinx / xilinx-vip.c
1 /*
2  * Xilinx Video IP Core
3  *
4  * Copyright (C) 2013-2015 Ideas on Board
5  * Copyright (C) 2013-2015 Xilinx, Inc.
6  *
7  * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
8  *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14
15 #include <linux/clk.h>
16 #include <linux/export.h>
17 #include <linux/kernel.h>
18 #include <linux/of.h>
19 #include <linux/platform_device.h>
20
21 #include <dt-bindings/media/xilinx-vip.h>
22
23 #include "xilinx-vip.h"
24
25 /* -----------------------------------------------------------------------------
26  * Helper functions
27  */
28
29 static const struct xvip_video_format xvip_video_formats[] = {
30         { XVIP_VF_YUV_420, 8, NULL, MEDIA_BUS_FMT_VYYUYY8_1X24,
31           1, 12, V4L2_PIX_FMT_NV12, 2, 1, 1, 2, "4:2:0, semi-planar, YUV" },
32         { XVIP_VF_YUV_420, 8, NULL, MEDIA_BUS_FMT_VYYUYY8_1X24,
33           1, 12, V4L2_PIX_FMT_NV12M, 2, 2, 1, 2, "4:2:0, 2-plane non-cont" },
34         { XVIP_VF_YUV_420, 10, NULL, MEDIA_BUS_FMT_VYYUYY10_4X20,
35           1, 12, V4L2_PIX_FMT_XV15, 2, 1, 2, 2, "4:2:0, 10-bit 2-plane cont" },
36         { XVIP_VF_YUV_420, 10, NULL, MEDIA_BUS_FMT_VYYUYY10_4X20,
37           1, 12, V4L2_PIX_FMT_XV15M, 2, 2, 1, 2, "4:2:0, 10-bit 2-plane non-cont" },
38         { XVIP_VF_YUV_420, 12, NULL, MEDIA_BUS_FMT_UYYVYY12_4X24,
39           1, 12, V4L2_PIX_FMT_X012, 2, 1, 2, 2, "4:2:0, 12-bit 2-plane cont" },
40         { XVIP_VF_YUV_420, 12, NULL, MEDIA_BUS_FMT_UYYVYY12_4X24,
41           1, 12, V4L2_PIX_FMT_X012M, 2, 2, 1, 2, "4:2:0, 12-bit 2-plane non-cont" },
42         { XVIP_VF_YUV_420, 16, NULL, MEDIA_BUS_FMT_UYYVYY16_4X32,
43           2, 12, V4L2_PIX_FMT_X016, 2, 1, 2, 2, "4:2:0, 16-bit 2-plane cont" },
44         { XVIP_VF_YUV_420, 16, NULL, MEDIA_BUS_FMT_UYYVYY16_4X32,
45           2, 12, V4L2_PIX_FMT_X016M, 2, 2, 1, 2, "4:2:0, 16-bit 2-plane non-cont" },
46         { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
47           2, 16, V4L2_PIX_FMT_YUYV, 1, 1, 2, 1, "4:2:2, packed, YUYV" },
48         { XVIP_VF_VUY_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
49           2, 16, V4L2_PIX_FMT_UYVY, 1, 1, 2, 1, "4:2:2, packed, UYVY" },
50         { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
51           1, 16, V4L2_PIX_FMT_NV16, 2, 1, 1, 1, "4:2:2, semi-planar, YUV" },
52         { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
53           1, 16, V4L2_PIX_FMT_NV16M, 2, 2, 1, 1, "4:2:2, 2-plane non-contiguous" },
54         { XVIP_VF_YUV_422, 10, NULL, MEDIA_BUS_FMT_UYVY10_1X20,
55           1, 16, V4L2_PIX_FMT_XV20, 2, 1, 2, 1, "4:2:2, 10-bit 2-plane cont" },
56         { XVIP_VF_YUV_422, 10, NULL, MEDIA_BUS_FMT_UYVY10_1X20,
57           1, 16, V4L2_PIX_FMT_XV20M, 2, 2, 1, 1, "4:2:2, 10-bit 2-plane non-cont" },
58         { XVIP_VF_YUV_422, 12, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
59           1, 16, V4L2_PIX_FMT_X212, 2, 1, 2, 1, "4:2:2, 12-bit 2-plane cont" },
60         { XVIP_VF_YUV_422, 12, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
61           1, 16, V4L2_PIX_FMT_X212M, 2, 2, 1, 1, "4:2:2, 12-bit 2-plane non-cont" },
62         { XVIP_VF_YUV_422, 16, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
63           2, 16, V4L2_PIX_FMT_X216, 2, 1, 2, 1, "4:2:2, 16-bit 2-plane cont" },
64         { XVIP_VF_YUV_422, 16, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
65           2, 16, V4L2_PIX_FMT_X216M, 2, 2, 1, 1, "4:2:2, 16-bit 2-plane non-cont" },
66         { XVIP_VF_YUV_444, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
67           3, 24, V4L2_PIX_FMT_VUY24, 1, 1, 1, 1, "4:4:4, packed, YUYV" },
68         { XVIP_VF_YUVX, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
69           4, 32, V4L2_PIX_FMT_XVUY32, 1, 1, 1, 1, "X:4:4:4, packed, YUYV" },
70         { XVIP_VF_YUVX, 10, NULL, MEDIA_BUS_FMT_VUY10_1X30,
71           3, 32, V4L2_PIX_FMT_XVUY10, 1, 1, 1, 1, "2:10:10:10, packed, XVUY" },
72         { XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
73           3, 24, V4L2_PIX_FMT_BGR24, 1, 1, 1, 1, "24-bit RGB" },
74         { XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
75           3, 24, V4L2_PIX_FMT_RGB24, 1, 1, 1, 1, "24-bit RGB" },
76         { XVIP_VF_BGRX, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
77           4, 32, V4L2_PIX_FMT_BGRX32, 1, 1, 1, 1, "x:8:8:8 RGB w/8 bits padding" },
78         { XVIP_VF_XRGB, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
79           4, 32, V4L2_PIX_FMT_XBGR32, 1, 1, 1, 1, "8:8:8:x RGBx w/8 bits padding" },
80         { XVIP_VF_XBGR, 10, NULL, MEDIA_BUS_FMT_RBG101010_1X30,
81           3, 32, V4L2_PIX_FMT_XBGR30, 1, 1, 1, 1, "2:10:10:10, packed, XBGR" },
82         { XVIP_VF_XBGR, 12, NULL, MEDIA_BUS_FMT_RBG121212_1X36,
83           3, 40, V4L2_PIX_FMT_XBGR40, 1, 1, 1, 1, "4:12:12:12, packed, XBGR" },
84         { XVIP_VF_RBG, 16, NULL, MEDIA_BUS_FMT_RBG161616_1X48,
85           6, 48, V4L2_PIX_FMT_BGR48, 1, 1, 1, 1, "48-bit RGB" },
86         { XVIP_VF_MONO_SENSOR, 8, "mono", MEDIA_BUS_FMT_Y8_1X8,
87           1, 8, V4L2_PIX_FMT_GREY, 1, 1, 1, 1, "Greyscale 8-bit" },
88         { XVIP_VF_Y_GREY, 10, NULL, MEDIA_BUS_FMT_Y10_1X10,
89           4, 32, V4L2_PIX_FMT_XY10, 1, 1, 1, 1, "2:10:10:10, Grey, xY1Y2Y3Y4" },
90         { XVIP_VF_Y_GREY, 12, NULL, MEDIA_BUS_FMT_Y12_1X12,
91           1, 12, V4L2_PIX_FMT_XY12, 1, 1, 1, 1, "4:12:12:12, packed, xY1Y2Y3" },
92         { XVIP_VF_Y_GREY, 16, NULL, MEDIA_BUS_FMT_Y16_1X16,
93           2, 16, V4L2_PIX_FMT_Y16, 1, 1, 1, 1, "Greyscale 16-bit" },
94         { XVIP_VF_MONO_SENSOR, 8, "rggb", MEDIA_BUS_FMT_SRGGB8_1X8,
95           1, 8, V4L2_PIX_FMT_SGRBG8, 1, 1, 1, 1, "Bayer 8-bit RGGB" },
96         { XVIP_VF_MONO_SENSOR, 8, "grbg", MEDIA_BUS_FMT_SGRBG8_1X8,
97           1, 8, V4L2_PIX_FMT_SGRBG8, 1, 1, 1, 1, "Bayer 8-bit GRBG" },
98         { XVIP_VF_MONO_SENSOR, 8, "gbrg", MEDIA_BUS_FMT_SGBRG8_1X8,
99           1, 8, V4L2_PIX_FMT_SGBRG8, 1, 1, 1, 1, "Bayer 8-bit GBRG" },
100         { XVIP_VF_MONO_SENSOR, 8, "bggr", MEDIA_BUS_FMT_SBGGR8_1X8,
101           1, 8, V4L2_PIX_FMT_SBGGR8, 1, 1, 1, 1, "Bayer 8-bit BGGR" },
102         { XVIP_VF_MONO_SENSOR, 12, "rggb", MEDIA_BUS_FMT_SRGGB12_1X12,
103           1, 12, V4L2_PIX_FMT_SRGGB12, 1, 1, 1, 1, "Bayer 12-bit RGGB" },
104         { XVIP_VF_MONO_SENSOR, 12, "grbg", MEDIA_BUS_FMT_SGRBG12_1X12,
105           1, 12, V4L2_PIX_FMT_SGRBG12, 1, 1, 1, 1, "Bayer 12-bit GRBG" },
106         { XVIP_VF_MONO_SENSOR, 12, "gbrg", MEDIA_BUS_FMT_SGBRG12_1X12,
107           1, 12, V4L2_PIX_FMT_SGBRG12, 1, 1, 1, 1, "Bayer 12-bit GBRG" },
108         { XVIP_VF_MONO_SENSOR, 12, "bggr", MEDIA_BUS_FMT_SBGGR12_1X12,
109           1, 12, V4L2_PIX_FMT_SBGGR12, 1, 1, 1, 1, "Bayer 12-bit BGGR" },
110         { XVIP_VF_MONO_SENSOR, 16, "rggb", MEDIA_BUS_FMT_SRGGB16_1X16,
111           1, 16, V4L2_PIX_FMT_SRGGB16, 1, 1, 1, 1, "Bayer 16-bit RGGB" },
112         { XVIP_VF_MONO_SENSOR, 16, "grbg", MEDIA_BUS_FMT_SGRBG16_1X16,
113           1, 12, V4L2_PIX_FMT_SGRBG16, 1, 1, 1, 1, "Bayer 16-bit GRBG" },
114         { XVIP_VF_MONO_SENSOR, 16, "gbrg", MEDIA_BUS_FMT_SGBRG16_1X16,
115           1, 12, V4L2_PIX_FMT_SGBRG16, 1, 1, 1, 1, "Bayer 16-bit GBRG" },
116         { XVIP_VF_MONO_SENSOR, 16, "bggr", MEDIA_BUS_FMT_SBGGR12_1X12,
117           1, 12, V4L2_PIX_FMT_SBGGR16, 1, 1, 1, 1, "Bayer 16-bit BGGR" },
118 };
119
120 /**
121  * xvip_get_format_by_code - Retrieve format information for a media bus code
122  * @code: the format media bus code
123  *
124  * Return: a pointer to the format information structure corresponding to the
125  * given V4L2 media bus format @code, or ERR_PTR if no corresponding format can
126  * be found.
127  */
128 const struct xvip_video_format *xvip_get_format_by_code(unsigned int code)
129 {
130         unsigned int i;
131
132         for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
133                 const struct xvip_video_format *format = &xvip_video_formats[i];
134
135                 if (format->code == code)
136                         return format;
137         }
138
139         return ERR_PTR(-EINVAL);
140 }
141 EXPORT_SYMBOL_GPL(xvip_get_format_by_code);
142
143 /**
144  * xvip_get_format_by_fourcc - Retrieve format information for a 4CC
145  * @fourcc: the format 4CC
146  *
147  * Return: a pointer to the format information structure corresponding to the
148  * given V4L2 format @fourcc, or ERR_PTR if no corresponding format can be
149  * found.
150  */
151 const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc)
152 {
153         unsigned int i;
154
155         for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
156                 const struct xvip_video_format *format = &xvip_video_formats[i];
157
158                 if (format->fourcc == fourcc)
159                         return format;
160         }
161
162         return ERR_PTR(-EINVAL);
163 }
164 EXPORT_SYMBOL_GPL(xvip_get_format_by_fourcc);
165
166 /**
167  * xvip_bpl_scaling_factor - Retrieve bpl scaling factor for a 4CC
168  * @fourcc: the format 4CC
169  * @numerator: returning numerator of scaling factor
170  * @denominator: returning denominator of scaling factor
171  *
172  * Return: Return numerator and denominator values by address
173  */
174 void xvip_bpl_scaling_factor(u32 fourcc, u32 *numerator, u32 *denominator)
175 {
176         switch (fourcc) {
177         case V4L2_PIX_FMT_XY10:
178         case V4L2_PIX_FMT_XV15:
179         case V4L2_PIX_FMT_XV20:
180         case V4L2_PIX_FMT_XV15M:
181         case V4L2_PIX_FMT_XV20M:
182         case V4L2_PIX_FMT_XBGR30:
183         case V4L2_PIX_FMT_XVUY10:
184                 *numerator = 10;
185                 *denominator = 8;
186                 break;
187         case V4L2_PIX_FMT_XBGR40:
188         case V4L2_PIX_FMT_XY12:
189         case V4L2_PIX_FMT_X012:
190         case V4L2_PIX_FMT_X012M:
191         case V4L2_PIX_FMT_X212:
192         case V4L2_PIX_FMT_X212M:
193                 *numerator = 12;
194                 *denominator = 8;
195                 break;
196         default:
197                 *numerator = 1;
198                 *denominator = 1;
199                 break;
200         }
201 }
202 EXPORT_SYMBOL_GPL(xvip_bpl_scaling_factor);
203
204 /**
205  * xvip_width_padding_factor - Retrieve width's padding factor for a 4CC
206  * @fourcc: the format 4CC
207  * @numerator: returning numerator of padding factor
208  * @denominator: returning denominator of padding factor
209  *
210  * Return: Return numerator and denominator values by address
211  */
212 void xvip_width_padding_factor(u32 fourcc, u32 *numerator, u32 *denominator)
213 {
214         switch (fourcc) {
215         case V4L2_PIX_FMT_XY10:
216         case V4L2_PIX_FMT_XV15:
217         case V4L2_PIX_FMT_XV20:
218         case V4L2_PIX_FMT_XV15M:
219         case V4L2_PIX_FMT_XV20M:
220         case V4L2_PIX_FMT_XBGR30:
221         case V4L2_PIX_FMT_XVUY10:
222                 /* 32 bits are required per 30 bits of data */
223                 *numerator = 32;
224                 *denominator = 30;
225                 break;
226         case V4L2_PIX_FMT_XBGR40:
227         case V4L2_PIX_FMT_XY12:
228         case V4L2_PIX_FMT_X012:
229         case V4L2_PIX_FMT_X012M:
230         case V4L2_PIX_FMT_X212:
231         case V4L2_PIX_FMT_X212M:
232                 *numerator = 40;
233                 *denominator = 36;
234                 break;
235         default:
236                 *numerator = 1;
237                 *denominator = 1;
238                 break;
239         }
240 }
241 EXPORT_SYMBOL_GPL(xvip_width_padding_factor);
242
243 /**
244  * xvip_of_get_format - Parse a device tree node and return format information
245  * @node: the device tree node
246  *
247  * Read the xlnx,video-format, xlnx,video-width and xlnx,cfa-pattern properties
248  * from the device tree @node passed as an argument and return the corresponding
249  * format information.
250  *
251  * Return: a pointer to the format information structure corresponding to the
252  * format name and width, or ERR_PTR if no corresponding format can be found.
253  */
254 const struct xvip_video_format *xvip_of_get_format(struct device_node *node)
255 {
256         const char *pattern = "mono";
257         unsigned int vf_code;
258         unsigned int i;
259         u32 width;
260         int ret;
261
262         ret = of_property_read_u32(node, "xlnx,video-format", &vf_code);
263         if (ret < 0)
264                 return ERR_PTR(ret);
265
266         ret = of_property_read_u32(node, "xlnx,video-width", &width);
267         if (ret < 0)
268                 return ERR_PTR(ret);
269
270         if (vf_code == XVIP_VF_MONO_SENSOR)
271                 of_property_read_string(node, "xlnx,cfa-pattern", &pattern);
272
273         for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
274                 const struct xvip_video_format *format = &xvip_video_formats[i];
275
276                 if (format->vf_code != vf_code || format->width != width)
277                         continue;
278
279                 if (vf_code == XVIP_VF_MONO_SENSOR &&
280                     strcmp(pattern, format->pattern))
281                         continue;
282
283                 return format;
284         }
285
286         return ERR_PTR(-EINVAL);
287 }
288 EXPORT_SYMBOL_GPL(xvip_of_get_format);
289
290 /**
291  * xvip_set_format_size - Set the media bus frame format size
292  * @format: V4L2 frame format on media bus
293  * @fmt: media bus format
294  *
295  * Set the media bus frame format size. The width / height from the subdevice
296  * format are set to the given media bus format. The new format size is stored
297  * in @format. The width and height are clamped using default min / max values.
298  */
299 void xvip_set_format_size(struct v4l2_mbus_framefmt *format,
300                           const struct v4l2_subdev_format *fmt)
301 {
302         format->width = clamp_t(unsigned int, fmt->format.width,
303                                 XVIP_MIN_WIDTH, XVIP_MAX_WIDTH);
304         format->height = clamp_t(unsigned int, fmt->format.height,
305                          XVIP_MIN_HEIGHT, XVIP_MAX_HEIGHT);
306 }
307 EXPORT_SYMBOL_GPL(xvip_set_format_size);
308
309 /**
310  * xvip_clr_or_set - Clear or set the register with a bitmask
311  * @xvip: Xilinx Video IP device
312  * @addr: address of register
313  * @mask: bitmask to be set or cleared
314  * @set: boolean flag indicating whether to set or clear
315  *
316  * Clear or set the register at address @addr with a bitmask @mask depending on
317  * the boolean flag @set. When the flag @set is true, the bitmask is set in
318  * the register, otherwise the bitmask is cleared from the register
319  * when the flag @set is false.
320  *
321  * Fox eample, this function can be used to set a control with a boolean value
322  * requested by users. If the caller knows whether to set or clear in the first
323  * place, the caller should call xvip_clr() or xvip_set() directly instead of
324  * using this function.
325  */
326 void xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set)
327 {
328         u32 reg;
329
330         reg = xvip_read(xvip, addr);
331         reg = set ? reg | mask : reg & ~mask;
332         xvip_write(xvip, addr, reg);
333 }
334 EXPORT_SYMBOL_GPL(xvip_clr_or_set);
335
336 /**
337  * xvip_clr_and_set - Clear and set the register with a bitmask
338  * @xvip: Xilinx Video IP device
339  * @addr: address of register
340  * @clr: bitmask to be cleared
341  * @set: bitmask to be set
342  *
343  * Clear a bit(s) of mask @clr in the register at address @addr, then set
344  * a bit(s) of mask @set in the register after.
345  */
346 void xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set)
347 {
348         u32 reg;
349
350         reg = xvip_read(xvip, addr);
351         reg &= ~clr;
352         reg |= set;
353         xvip_write(xvip, addr, reg);
354 }
355 EXPORT_SYMBOL_GPL(xvip_clr_and_set);
356
357 int xvip_init_resources(struct xvip_device *xvip)
358 {
359         struct platform_device *pdev = to_platform_device(xvip->dev);
360         struct resource *res;
361
362         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
363         xvip->iomem = devm_ioremap_resource(xvip->dev, res);
364         if (IS_ERR(xvip->iomem))
365                 return PTR_ERR(xvip->iomem);
366
367         xvip->clk = devm_clk_get(xvip->dev, NULL);
368         if (IS_ERR(xvip->clk))
369                 return PTR_ERR(xvip->clk);
370
371         clk_prepare_enable(xvip->clk);
372         return 0;
373 }
374 EXPORT_SYMBOL_GPL(xvip_init_resources);
375
376 void xvip_cleanup_resources(struct xvip_device *xvip)
377 {
378         clk_disable_unprepare(xvip->clk);
379 }
380 EXPORT_SYMBOL_GPL(xvip_cleanup_resources);
381
382 /* -----------------------------------------------------------------------------
383  * Subdev operations handlers
384  */
385
386 /**
387  * xvip_enum_mbus_code - Enumerate the media format code
388  * @subdev: V4L2 subdevice
389  * @cfg: V4L2 subdev pad configuration
390  * @code: returning media bus code
391  *
392  * Enumerate the media bus code of the subdevice. Return the corresponding
393  * pad format code. This function only works for subdevices with fixed format
394  * on all pads. Subdevices with multiple format should have their own
395  * function to enumerate mbus codes.
396  *
397  * Return: 0 if the media bus code is found, or -EINVAL if the format index
398  * is not valid.
399  */
400 int xvip_enum_mbus_code(struct v4l2_subdev *subdev,
401                         struct v4l2_subdev_pad_config *cfg,
402                         struct v4l2_subdev_mbus_code_enum *code)
403 {
404         struct v4l2_mbus_framefmt *format;
405
406         /* Enumerating frame sizes based on the active configuration isn't
407          * supported yet.
408          */
409         if (code->which == V4L2_SUBDEV_FORMAT_ACTIVE)
410                 return -EINVAL;
411
412         if (code->index)
413                 return -EINVAL;
414
415         format = v4l2_subdev_get_try_format(subdev, cfg, code->pad);
416
417         code->code = format->code;
418
419         return 0;
420 }
421 EXPORT_SYMBOL_GPL(xvip_enum_mbus_code);
422
423 /**
424  * xvip_enum_frame_size - Enumerate the media bus frame size
425  * @subdev: V4L2 subdevice
426  * @cfg: V4L2 subdev pad configuration
427  * @fse: returning media bus frame size
428  *
429  * This function is a drop-in implementation of the subdev enum_frame_size pad
430  * operation. It assumes that the subdevice has one sink pad and one source
431  * pad, and that the format on the source pad is always identical to the
432  * format on the sink pad. Entities with different requirements need to
433  * implement their own enum_frame_size handlers.
434  *
435  * Return: 0 if the media bus frame size is found, or -EINVAL
436  * if the index or the code is not valid.
437  */
438 int xvip_enum_frame_size(struct v4l2_subdev *subdev,
439                          struct v4l2_subdev_pad_config *cfg,
440                          struct v4l2_subdev_frame_size_enum *fse)
441 {
442         struct v4l2_mbus_framefmt *format;
443
444         /* Enumerating frame sizes based on the active configuration isn't
445          * supported yet.
446          */
447         if (fse->which == V4L2_SUBDEV_FORMAT_ACTIVE)
448                 return -EINVAL;
449
450         format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
451
452         if (fse->index || fse->code != format->code)
453                 return -EINVAL;
454
455         if (fse->pad == XVIP_PAD_SINK) {
456                 fse->min_width = XVIP_MIN_WIDTH;
457                 fse->max_width = XVIP_MAX_WIDTH;
458                 fse->min_height = XVIP_MIN_HEIGHT;
459                 fse->max_height = XVIP_MAX_HEIGHT;
460         } else {
461                 /* The size on the source pad is fixed and always identical to
462                  * the size on the sink pad.
463                  */
464                 fse->min_width = format->width;
465                 fse->max_width = format->width;
466                 fse->min_height = format->height;
467                 fse->max_height = format->height;
468         }
469
470         return 0;
471 }
472 EXPORT_SYMBOL_GPL(xvip_enum_frame_size);